package edu.brown.designer.generators;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.apache.log4j.Logger;
import org.voltdb.CatalogContext;
import org.voltdb.catalog.Column;
import org.voltdb.catalog.ColumnRef;
import org.voltdb.catalog.Constraint;
import org.voltdb.catalog.Table;
import org.voltdb.types.ConstraintType;
import edu.brown.designer.DependencyGraph;
import edu.brown.designer.DesignerEdge;
import edu.brown.designer.DesignerInfo;
import edu.brown.designer.DesignerVertex;
import edu.brown.graphs.AbstractDirectedGraph;
import edu.brown.utils.PredicatePairs;
import edu.brown.workload.Workload;
import edu.uci.ics.jung.graph.util.EdgeType;
/**
* @author pavlo
*/
public class DependencyGraphGenerator extends AbstractGenerator<AbstractDirectedGraph<DesignerVertex, DesignerEdge>> {
private static final Logger LOG = Logger.getLogger(DependencyGraphGenerator.class);
public DependencyGraphGenerator(DesignerInfo info) {
super(info);
}
/**
* Convenience method for generating a DependencyGraph
*
* @param catalog_db
* @return
*/
public static DependencyGraph generate(CatalogContext catalogContext) {
DependencyGraph dgraph = new DependencyGraph(catalogContext.database);
DesignerInfo info = new DesignerInfo(catalogContext, new Workload(catalogContext.catalog));
try {
new DependencyGraphGenerator(info).generate(dgraph);
} catch (Exception ex) {
ex.printStackTrace();
return (null);
}
return (dgraph);
}
public void generate(AbstractDirectedGraph<DesignerVertex, DesignerEdge> graph) throws Exception {
Collection<Table> catalog_tables = info.catalogContext.getDataTables();
for (Table catalog_table : catalog_tables) {
assert (catalog_table.getSystable() == false) : "Unexpected " + catalog_table;
graph.addVertex(new DesignerVertex(catalog_table));
} // FOR
//
// We first need to generate the list of candidate root tables
// These are the tables that do not have any foreign key references
//
Map<DesignerVertex, List<Column>> fkey_ref_cols = new HashMap<DesignerVertex, List<Column>>();
Map<DesignerVertex, List<Constraint>> fkey_ref_consts = new HashMap<DesignerVertex, List<Constraint>>();
for (Table catalog_table : catalog_tables) {
DesignerVertex vertex = graph.getVertex(catalog_table);
fkey_ref_cols.put(vertex, new ArrayList<Column>());
fkey_ref_consts.put(vertex, new ArrayList<Constraint>());
LOG.debug("Inspecting table '" + catalog_table.getName() + "'");
//
// Constraints
//
for (Constraint catalog_const : catalog_table.getConstraints()) {
//
// Foreign Key Constraint
//
if (catalog_const.getType() == ConstraintType.FOREIGN_KEY.getValue()) {
if (catalog_const.getForeignkeytable() == null) {
throw new Exception("ERROR: The table is null for foreign key constraint '" + catalog_const + "' for table '" + catalog_table + "'");
} else if (catalog_const.getForeignkeycols().isEmpty()) {
throw new Exception("ERROR: The list of columns are empty for foreign key constraint '" + catalog_const + "' for table '" + catalog_table + "'");
}
for (ColumnRef catalog_col_ref : catalog_const.getForeignkeycols()) {
fkey_ref_cols.get(vertex).add(catalog_col_ref.getColumn());
} // FOR
fkey_ref_consts.get(vertex).add(catalog_const);
}
} // FOR
//
// Columns ????????
//
// for (Column catalog_col : catalog_table.getColumns()) {
// LOG.debug("Inspecting column '" + catalog_col.getName() +
// "' in table '" + catalog_table.getName() + "'");
// } // FOR
} // FOR
//
// Build the dependency graph's edges
//
for (Table catalog_table : catalog_tables) {
// For each vertex, get the list of foreign key references to point
// to it and
// make a new edge between the parent and child
DesignerVertex vertex = graph.getVertex(catalog_table);
for (int ctr = 0, cnt = fkey_ref_consts.get(vertex).size(); ctr < cnt; ctr++) {
Constraint catalog_const = fkey_ref_consts.get(vertex).get(ctr);
Column catalog_col = fkey_ref_cols.get(vertex).get(ctr);
//
// Grab the table object used in this foreign key constraint
// We then get the vertex that we're using to represent it
//
Table catalog_fkey_table = catalog_const.getForeignkeytable();
DesignerVertex other_vertex = graph.getVertex(catalog_fkey_table);
if (other_vertex == null) {
throw new Exception("ERROR: The constraint '" + catalog_const + "' on '" + vertex + "' uses an unknown table '" + catalog_fkey_table.getName() + "'");
}
PredicatePairs cset = new PredicatePairs();
// FIXME cset.add(catalog_const.getFkeycolumn, catalog_col);
DesignerEdge edge = new DesignerEdge(graph);
edge.setAttribute(DependencyGraph.EdgeAttributes.CONSTRAINT.name(), catalog_const);
edge.setAttribute(DependencyGraph.EdgeAttributes.COLUMNSET.name(), cset);
graph.addEdge(edge, other_vertex, vertex, EdgeType.DIRECTED);
} // FOR
} // FOR
}
}