/*
* Copyright [1999-2015] Wellcome Trust Sanger Institute and the EMBL-European Bioinformatics Institute
* Copyright [2016-2017] EMBL-European Bioinformatics Institute
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ensembl.healthcheck.testcase.eg_compara;
import java.sql.Connection;
import org.ensembl.healthcheck.ReportManager;
import org.ensembl.healthcheck.util.DBUtils;
/**
* Performs checks between the member table and the gene tree member table
* ensuring all applicable entities are linked
*
* @author ayates
*/
public class EGForeignKeyGeneTreeMemberId extends AbstractEGForeignKeyMemberId {
/**
* <p>
* Overridden behaviour. In this class we want to check for orphans, but
* allow the linking column of the target table (table1) to be null.
* </p>
*
* <p>
* This is important for the gene_tree_node table, in which the member_id
* is null for internal nodes of trees. Only leaf nodes link to member.
* Therefore we are only interested in rows having a member_id that does
* not link to any member.
* </p>
*/
public boolean checkForOrphans(
Connection con,
String table1,
String col1,
String table2,
String col2) {
return checkForOrphans(con, table1, col1, table2, col2, true);
}
/**
* checkForOrphans method with an optional parameter for skipping rows
* with a column that doesn't link, because it is null.
*
*/
public boolean checkForOrphans(
Connection con,
String table1,
String col1,
String table2,
String col2,
boolean ignoreTargetNulls
) {
if (ignoreTargetNulls) {
return checkForOrphansNotNull(con, table1, col1, table2, col2);
} else {
return super.checkForOrphans(con, table1, col1, table2, col2);
}
}
/**
* An implementation similar to
*
* @see #checkForOrphans(Connection, String, String, String, String)
*
* but this one only searches for orphans in which the key column of the
* target table is not null.
*
*/
public boolean checkForOrphansNotNull(
Connection con,
String table1,
String col1,
String table2,
String col2
) {
int orphans = 0;
boolean result = true;
orphans = countOrphansIgnoreTable1Nulls(con, table1, col1, table2, col2);
String useful_sql = "SELECT " + table1 + "." + col1 + generateSqlFromClause(table1, col1, table2, col2);
if (orphans > 0) {
ReportManager.problem(this, con, "FAILED " + table1 + " -> "
+ table2 + " using FK " + col1 + "(" + col2 + ")"
+ " relationships");
ReportManager.problem(this, con, "FAILURE DETAILS: " + orphans
+ " " + table1 + " entries are not linked to " + table2);
ReportManager.problem(this, con, "USEFUL SQL: " + useful_sql);
result = false;
} else if (orphans < 0) {
ReportManager.problem(this, con, "TEST NOT COMPLETED " + table1
+ " -> " + table2 + " using FK " + col1
+ ", look at the StackTrace if any");
result = false;
}
return result;
}
public int countOrphansIgnoreTable1Nulls(
Connection con,
String table1,
String col1,
String table2,
String col2) {
String sql = "SELECT COUNT(*)" + generateSqlFromClause(table1, col1, table2, col2);
//logger.info(sql);
int resultLeft = DBUtils.getRowCount(con, sql);
if (resultLeft > 0) {
String[] values = DBUtils.getColumnValues(con, "SELECT " + table1
+ "." + col1 + sql + " LIMIT 20");
for (int i = 0; i < values.length; i++) {
ReportManager.info(this, con, table1 + "." + col1 + " "
+ values[i] + " is not linked.");
}
}
return resultLeft;
}
protected String generateSqlFromClause(
String table1,
String col1,
String table2,
String col2) {
return " FROM " + table1 + " LEFT JOIN " + table2 + " ON "
+ table1 + "." + col1 + " = " + table2 + "." + col2 + " WHERE "
+ table2 + "." + col2 + " IS NULL and "+ table1+"."+col1+" is not null";
}
@Override
protected String getTargetTable() {
return "gene_tree_node";
}
protected String getSourceTable() {
return "seq_member";
}
protected String getSourceField() {
return "seq_member_id";
}
}