/* * 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. */ /* * Copyright (C) 2004 EBI, GRL * * This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by * the Free Software Foundation; either version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public License along with this library; if not, write to the Free Software Foundation, * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package org.ensembl.healthcheck.testcase.funcgen; import java.sql.Connection; import java.sql.ResultSet; import java.sql.SQLException; import org.ensembl.healthcheck.DatabaseRegistryEntry; import org.ensembl.healthcheck.ReportManager; import org.ensembl.healthcheck.testcase.generic.CoreForeignKeys; import org.ensembl.healthcheck.Team; /** * An EnsEMBL Healthcheck test case that looks for broken foreign-key relationships. */ public class FuncgenForeignKeys extends CoreForeignKeys { /** * Create an OrphanTestCase that applies to a specific set of databases. */ public FuncgenForeignKeys() { addToGroup("post_regbuild"); addToGroup("funcgen-release"); addToGroup("funcgen"); setDescription("Check for broken foreign-key relationships."); setHintLongRunning(true); setTeamResponsible(Team.FUNCGEN); removeSecondTeamResponsible(); // Does not appear to be imported } /** * Look for broken foreign key relationships. * * @param dbre * The database to use. * @return true if all foreign key relationships are valid. */ public boolean run(DatabaseRegistryEntry dbre) { boolean result = true; Connection con = dbre.getConnection(); String[] featTabs = getFuncgenFeatureTables(); //We need to write a new method here to handle denormalised link tables try{ result &= checkForOrphans(con, "annotated_feature", "feature_set_id", "feature_set", "feature_set_id", true); result &= checkForOrphans(con, "array", "array_id", "array_chip", "array_id", false); // ---------------------------- // Ensure that we have no orphaned associate_feature_types result &= checkForOrphans(con, "associated_feature_type", "feature_type_id", "feature_type", "feature_type_id", true); // Get table_names from associated_feature_type try { ResultSet rs = con.createStatement().executeQuery("SELECT distinct(table_name) from associated_feature_type"); while (rs.next()){ String tableName = rs.getString(1); result &= checkForOrphansWithConstraint(con, "associated_feature_type", "table_id", tableName, tableName + "_id", "table_name='" + tableName + "'"); } rs.close(); } catch (SQLException se) { se.printStackTrace(); return false; } //Need a constraint here where fs.epigenome_id is NOT NULL //result &= checkForOrphans(con, "feature_set", "epigenome_id", "epigenome", "epigenome_id", true); result &= checkForOrphansWithConstraint(con, "feature_set", "epigenome_id", "epigenome", "epigenome_id", "epigenome_id IS NOT NULL"); result &= checkForOrphans(con, "result_set", "epigenome_id", "epigenome", "epigenome_id", true); //This may fail as it's not necessary to have a epigenome_id in a result_set??? result &= checkForOrphans(con, "data_set", "data_set_id", "supporting_set", "data_set_id", false); result &= checkForOrphansWithConstraint(con, "data_set", "feature_set_id", "feature_set", "feature_set_id", "feature_set_id != 0"); result &= checkForOrphans(con, "input_subset", "experiment_id", "experiment", "experiment_id", true); result &= checkForOrphans(con, "experiment", "experimental_group_id", "experimental_group", "experimental_group_id", true); result &= checkForOrphans(con, "external_feature", "feature_set_id", "feature_set", "feature_set_id", true); result &= checkForOrphans(con, "feature_set", "analysis_id", "analysis", "analysis_id", true); result &= checkForOrphans(con, "feature_set", "feature_type_id", "feature_type", "feature_type_id", true); result &= checkForOrphans(con, "regulatory_feature", "feature_type_id", "feature_type", "feature_type_id", true); result &= checkForOrphans(con, "result_set", "feature_type_id", "feature_type", "feature_type_id", true); result &= checkForOrphans(con, "input_subset", "feature_type_id", "feature_type", "feature_type_id", true); result &= checkForOrphans(con, "input_subset", "epigenome_id", "epigenome", "epigenome_id", true); result &= checkForOrphans(con, "probe", "array_chip_id", "array_chip", "array_chip_id", false); //result &= checkForOrphans(con, "probe", "probe_set_id", "probe_set", "probe_set_id", false); result &= checkForOrphansWithConstraint(con, "probe", "probe_set_id", "probe_set", "probe_set_id", "probe_set_id !=0"); result &= checkForOrphans(con, "probe_set", "probe_set_id", "probe", "probe_set_id"); //result &= checkForOrphans(con, "probe", "probe_id", "probe_feature", "probe_id", false); //Can have unmapped probes or arrays result &= checkForOrphans(con, "probe_feature", "probe_id", "probe", "probe_id", true); result &= checkForOrphans(con, "probe_feature", "analysis_id", "analysis", "analysis_id", true); result &= checkForOrphans(con, "result_set", "analysis_id", "analysis", "analysis_id", true); result &= checkForOrphans(con, "status", "status_name_id", "status_name", "status_name_id", true); //This only checks for table_ids which have been orphaned by the input table try { ResultSet rs = con.createStatement().executeQuery("SELECT distinct(type) from supporting_set"); while (rs.next()){ String setType = rs.getString(1); result &= checkForOrphansWithConstraint(con, "supporting_set", "supporting_set_id", setType + "_set", setType + "_set_id", "type='" + setType + "'"); } rs.close(); } catch (SQLException se) { se.printStackTrace(); return false; } result &= checkForOrphans(con, "object_xref", "xref_id", "xref", "xref_id", true);//shouldn't this be false? result &= checkForOrphans(con, "xref", "external_db_id", "external_db", "external_db_id", true);//shouldn't this be false? result &= checkForOrphans(con, "external_synonym", "xref_id", "xref", "xref_id", true);//shouldn't this be false? result &= checkForOrphans(con, "identity_xref", "object_xref_id", "object_xref", "object_xref_id", true);//shouldn't this be false? // ---------------------------- // Check object xrefs point to existing objects try { ResultSet rs = con.createStatement().executeQuery("SELECT distinct(ensembl_object_type) from object_xref"); while (rs.next()){ String objType = rs.getString(1); result &= checkKeysByEnsemblObjectType(con, "object_xref", objType); } rs.close(); } catch (SQLException se) { se.printStackTrace(); return false; } // ---------------------------- // Ensure that feature tables reference existing seq_regions for (int i = 0; i < featTabs.length; i++) { String featTab = featTabs[i]; // skip large tables as this test takes an inordinately long time // if (featTab.equals("protein_align_feature") || featTab.equals("dna_align_feature") || featTab.equals("repeat_feature")) { // continue; // } result &= checkForOrphans(con, featTab, "seq_region_id", "seq_region", "seq_region_id", true); } result &= checkForOrphans(con, "analysis_description", "analysis_id", "analysis", "analysis_id", true);//shouldn't this be false? result &= checkForOrphans(con, "unmapped_object", "unmapped_reason_id", "unmapped_reason", "unmapped_reason_id", true); result &= checkForOrphans(con, "unmapped_object", "analysis_id", "analysis", "analysis_id", true); result &= checkOptionalRelation(con, "unmapped_object", "external_db_id", "external_db", "external_db_id"); // ---------------------------- // Check tables which reference the analysis table String[] analysisTabs = getFuncgenTablesWithAnalysisID(); for (int i = 0; i < analysisTabs.length; i++) { String analysisTab = analysisTabs[i]; // skip large tables as this test takes an inordinately long time //if (analysisTab.equals("protein_align_feature") || analysisTab.equals("dna_align_feature") || analysisTab.equals("repeat_feature")) { // continue; //} //Isn't this jsut checkForOrphansWithConstraint? //Or is this just allowing the analysisTab to contain NULLs if (countOrphansWithConstraint(con, analysisTab, "analysis_id", "analysis", "analysis_id", "analysis_id IS NOT NULL") > 0) { ReportManager.problem(this, con, "FAILED object_xref -> analysis using FK analysis_id relationships"); result = false; } } } catch(Exception e){ //Catch all possible exceptions ReportManager .problem( this, con, "HealthCheck generated an exception:\n\t" + e.getMessage()); result = false; } return result; } // ------------------------------------------------------------------------- } // FuncgenForeignKeys