Project

General

Profile

Download (5.44 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 org.apache.log4j.Logger;
12

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

    
18
/**
19
 * @author a.mueller
20
 * @since 09.08.2013
21
 *
22
 */
23
public class TreeIndexUpdater
24
        extends AuditedSchemaUpdaterStepBase
25
        implements ISchemaUpdaterStep {
26

    
27
    private static final Logger logger = Logger.getLogger(TreeIndexUpdater.class);
28

    
29
	private String indexColumnName = "treeIndex";
30
	private final String treeIdColumnName;
31
	private final String parentIdColumnName = "parent_id";
32

    
33
	public static final TreeIndexUpdater NewInstance(String stepName, String tableName, String treeIdColumnName, boolean includeAudTable){
34
		return new TreeIndexUpdater(stepName, tableName, treeIdColumnName, null, includeAudTable);
35
	}
36

    
37
	public static final TreeIndexUpdater NewInstance(String stepName, String tableName, String treeIdColumnName, String indexColumnName, boolean includeAudTable){
38
		return new TreeIndexUpdater(stepName, tableName, treeIdColumnName, indexColumnName, includeAudTable);
39
	}
40

    
41

    
42
	protected TreeIndexUpdater(String stepName, String tableName, String treeIdColumnName, String indexColumnName, boolean includeAudTable) {
43
		super(stepName, tableName, includeAudTable);
44
		this.treeIdColumnName = treeIdColumnName;
45
		this.indexColumnName = indexColumnName == null ? this.indexColumnName : indexColumnName;
46
	}
47

    
48
    @Override
49
    protected void invokeOnTable(String tableName, ICdmDataSource datasource,
50
            IProgressMonitor monitor, CaseType caseType, SchemaUpdateResult result) {
51
        try{
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
				result.addWarning(message, (String)null, getStepName());
133
			}
134

    
135
			return;
136
		}catch(Exception e){
137
		    String message = e.getMessage();
138
			monitor.warning(message, e);
139
			logger.error(message);
140
			result.addException(e, message, getStepName() + ", TreeIndexUpdater.invokeOnTable");
141
			return;
142
		}
143
	}
144

    
145
}
(32-32/35)