diff --git a/src/net/sourceforge/schemaspy/dbTypes/db2.properties b/src/net/sourceforge/schemaspy/dbTypes/db2.properties index 8af1aa9..58f8f97 100755 --- a/src/net/sourceforge/schemaspy/dbTypes/db2.properties +++ b/src/net/sourceforge/schemaspy/dbTypes/db2.properties @@ -4,6 +4,8 @@ connectionSpec=jdbc:db2: db=database name driver=COM.ibm.db2.jdbc.app.DB2Driver + +# you can use the -cp command line option if you prefer driverPath=c:/Program Files/IBM/SQLLIB/java/db2java.zip # if your driver returns failures like "stream already closed" then its metadata diff --git a/src/net/sourceforge/schemaspy/dbTypes/mssql.properties b/src/net/sourceforge/schemaspy/dbTypes/mssql.properties index ae62aea..ab7fabf 100755 --- a/src/net/sourceforge/schemaspy/dbTypes/mssql.properties +++ b/src/net/sourceforge/schemaspy/dbTypes/mssql.properties @@ -6,6 +6,8 @@ port=database port on host db=database name driver=com.microsoft.jdbc.sqlserver.SQLServerDriver + +# you can use the -cp command line option if you prefer driverPath=C:/Program Files/Microsoft SQL Server 2000 Driver for JDBC/lib/msbase.jar;C:/Program Files/Microsoft SQL Server 2000 Driver for JDBC/lib/mssqlserver.jar;C:/Program Files/Microsoft SQL Server 2000 Driver for JDBC/lib/msutil.jar # if your driver returns failures like "stream already closed" then its metadata diff --git a/src/net/sourceforge/schemaspy/dbTypes/mysql.properties b/src/net/sourceforge/schemaspy/dbTypes/mysql.properties index 4a8481d..cf3932a 100755 --- a/src/net/sourceforge/schemaspy/dbTypes/mysql.properties +++ b/src/net/sourceforge/schemaspy/dbTypes/mysql.properties @@ -5,6 +5,7 @@ db=path to database driver=com.mysql.jdbc.Driver # point this to whatever is appropriate on your machine...let me know if there's a standard path/jar +# you can use the -cp command line option if you prefer driverPath=c:/mysql/mysql-connector-java-3.2.0-alpha-bin.jar # if your driver returns failures like "stream already closed" then its metadata diff --git a/src/net/sourceforge/schemaspy/dbTypes/ora.properties b/src/net/sourceforge/schemaspy/dbTypes/ora.properties index 6db6d2c..cefefd3 100755 --- a/src/net/sourceforge/schemaspy/dbTypes/ora.properties +++ b/src/net/sourceforge/schemaspy/dbTypes/ora.properties @@ -4,6 +4,8 @@ connectionSpec=jdbc:oracle:oci8:@ db=database name (from TNSNAMES.ORA) driver=oracle.jdbc.driver.OracleDriver + +# you can use the -cp command line option if you prefer driverPath=c:/Oracle8I/ora81/jdbc/lib/classes12.zip # this Oracle driver's metadata services aren't thread safe so limit its access to one thread diff --git a/src/net/sourceforge/schemaspy/model/Table.java b/src/net/sourceforge/schemaspy/model/Table.java index 1f48346..b2a99d0 100755 --- a/src/net/sourceforge/schemaspy/model/Table.java +++ b/src/net/sourceforge/schemaspy/model/Table.java @@ -1,24 +1,9 @@ package net.sourceforge.schemaspy.model; -import java.io.Serializable; -import java.lang.reflect.Method; -import java.sql.DatabaseMetaData; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.SQLException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; -import java.util.TreeMap; -import java.util.TreeSet; +import java.io.*; +import java.lang.reflect.*; +import java.sql.*; +import java.util.*; public class Table implements Serializable { private final String schema; @@ -385,6 +370,22 @@ public int getNumChildren() { return numChildren; } + public int getNumRealChildren() { + int numChildren = 0; + + for (Iterator iter = getColumns().iterator(); iter.hasNext(); ) { + TableColumn column = (TableColumn)iter.next(); + Iterator childIter = column.getChildren().iterator(); + while (childIter.hasNext()) { + TableColumn childColumn = (TableColumn)childIter.next(); + if (!column.getChildConstraint(childColumn).isImplied()) + ++numChildren; + } + } + + return numChildren; + } + public int getNumParents() { int numParents = 0; @@ -396,6 +397,22 @@ public int getNumParents() { return numParents; } + public int getNumRealParents() { + int numParents = 0; + + for (Iterator iter = getColumns().iterator(); iter.hasNext(); ) { + TableColumn column = (TableColumn)iter.next(); + Iterator parentIter = column.getParents().iterator(); + while (parentIter.hasNext()) { + TableColumn parentColumn = (TableColumn)parentIter.next(); + if (!column.getParentConstraint(parentColumn).isImplied()) + ++numParents; + } + } + + return numParents; + } + public ForeignKeyConstraint removeAForeignKeyConstraint() { final List columns = getColumns(); int numParents = 0; diff --git a/src/net/sourceforge/schemaspy/model/TableColumn.java b/src/net/sourceforge/schemaspy/model/TableColumn.java index 5e7ccdf..63a904b 100755 --- a/src/net/sourceforge/schemaspy/model/TableColumn.java +++ b/src/net/sourceforge/schemaspy/model/TableColumn.java @@ -163,12 +163,18 @@ public void unlinkChildren() { children.clear(); } + /** + * Returns Set of TableColumns that have a real (or implied) foreign key that + * references this TableColumn. + * @return Set + */ public Set getChildren() { return children.keySet(); } /** - * returns the constraint that connects the specified column to this column (specified 'child' to this 'parent' column) + * returns the constraint that connects the specified column to this column + * (specified 'child' to this 'parent' column) */ public ForeignKeyConstraint getChildConstraint(TableColumn child) { return (ForeignKeyConstraint)children.get(child); diff --git a/src/net/sourceforge/schemaspy/view/DotFormatter.java b/src/net/sourceforge/schemaspy/view/DotFormatter.java index 4fc0c6d..6fe2a5a 100755 --- a/src/net/sourceforge/schemaspy/view/DotFormatter.java +++ b/src/net/sourceforge/schemaspy/view/DotFormatter.java @@ -1,42 +1,36 @@ package net.sourceforge.schemaspy.view; -import java.io.IOException; -import java.util.Collection; -import java.util.HashSet; -import java.util.Iterator; -import java.util.Set; -import java.util.TreeSet; -import net.sourceforge.schemaspy.model.Table; -import net.sourceforge.schemaspy.model.TableColumn; -import net.sourceforge.schemaspy.util.LineWriter; +import java.io.*; +import java.util.*; +import net.sourceforge.schemaspy.model.*; +import net.sourceforge.schemaspy.util.*; /** * Format table data into .dot format to feed to GraphVis' dot program. * * @author John Currier - * @version 1.0 */ public class DotFormatter { /** * Write relationships associated with the given table * * @param table Table - * @param out LineWriter + * @param dot LineWriter * @throws IOException * @return boolean true if implied relationships were written */ - public WriteStats writeRelationships(Table table, boolean includeImplied, boolean twoDegreesOfSeparation, LineWriter out) throws IOException { + public WriteStats writeRelationships(Table table, boolean includeImplied, boolean twoDegreesOfSeparation, LineWriter dot) throws IOException { Set tablesWritten = new HashSet(); WriteStats stats = new WriteStats(); boolean[] wroteImplied = new boolean[1]; DotTableFormatter formatter = new DotTableFormatter(); - writeDotHeader(includeImplied ? "impliedTwoDegreesRelationshipsGraph" : (twoDegreesOfSeparation ? "twoDegreesRelationshipsGraph" : "oneDegreeRelationshipsGraph"), out); + writeDotHeader(includeImplied ? "impliedTwoDegreesRelationshipsGraph" : (twoDegreesOfSeparation ? "twoDegreesRelationshipsGraph" : "oneDegreeRelationshipsGraph"), dot); Set relatedTables = getImmediateRelatives(table, includeImplied, wroteImplied); - formatter.writeNode(table, "", true, true, true, out); + formatter.writeNode(table, "", true, true, true, dot); Set relationships = formatter.getRelationships(table, includeImplied); tablesWritten.add(table); stats.wroteTable(table); @@ -48,7 +42,7 @@ public WriteStats writeRelationships(Table table, boolean includeImplied, boolea if (!tablesWritten.add(relatedTable)) continue; // already written - formatter.writeNode(relatedTable, "", true, false, false, out); + formatter.writeNode(relatedTable, "", true, false, false, dot); stats.wroteTable(relatedTable); relationships.addAll(formatter.getRelationships(relatedTable, table, includeImplied)); } @@ -66,7 +60,7 @@ public WriteStats writeRelationships(Table table, boolean includeImplied, boolea if (!tablesWritten.add(cousin)) continue; // already written relationships.addAll(formatter.getRelationships(cousin, relatedTable, includeImplied)); - formatter.writeNode(cousin, "", false, false, false, out); + formatter.writeNode(cousin, "", false, false, false, dot); stats.wroteTable(cousin); } } @@ -74,9 +68,9 @@ public WriteStats writeRelationships(Table table, boolean includeImplied, boolea iter = new TreeSet(relationships).iterator(); while (iter.hasNext()) - out.writeln(iter.next().toString()); + dot.writeln(iter.next().toString()); - out.writeln("}"); + dot.writeln("}"); stats.setWroteImplied(wroteImplied[0]); return stats; } @@ -120,30 +114,30 @@ private Set getImmediateRelatives(Table table, boolean includeImplied, boolean[] } - private void writeDotHeader(String name, LineWriter out) throws IOException { - out.writeln("digraph " + name + " {"); - out.writeln(" graph ["); - out.writeln(" rankdir=\"RL\""); - out.writeln(" bgcolor=\"" + StyleSheet.getBodyBackground() + "\""); - out.writeln(" concentrate=\"true\""); - out.writeln(" ];"); - out.writeln(" node ["); - out.writeln(" fontsize=\"11\""); - out.writeln(" shape=\"plaintext\""); - out.writeln(" ];"); + private void writeDotHeader(String name, LineWriter dot) throws IOException { + dot.writeln("digraph " + name + " {"); + dot.writeln(" graph ["); + dot.writeln(" rankdir=\"RL\""); + dot.writeln(" bgcolor=\"" + StyleSheet.getBodyBackground() + "\""); + dot.writeln(" concentrate=\"true\""); + dot.writeln(" ];"); + dot.writeln(" node ["); + dot.writeln(" fontsize=\"11\""); + dot.writeln(" shape=\"plaintext\""); + dot.writeln(" ];"); } - public int writeRelationships(Collection tables, boolean includeImplied, LineWriter out) throws IOException { + public int writeRelationships(Collection tables, boolean includeImplied, LineWriter dot) throws IOException { DotTableFormatter formatter = new DotTableFormatter(); int numWritten = 0; - writeDotHeader(includeImplied ? "impliedRelationshipsGraph" : "relationshipsGraph", out); + writeDotHeader(includeImplied ? "impliedRelationshipsGraph" : "relationshipsGraph", dot); Iterator iter = tables.iterator(); while (iter.hasNext()) { Table table = (Table)iter.next(); if (!table.isOrphan(includeImplied)) { - formatter.writeNode(table, "tables/", true, false, false, out); + formatter.writeNode(table, "tables/", true, false, false, dot); ++numWritten; } } @@ -156,9 +150,9 @@ public int writeRelationships(Collection tables, boolean includeImplied, LineWri iter = relationships.iterator(); while (iter.hasNext()) - out.writeln(iter.next().toString()); + dot.writeln(iter.next().toString()); - out.writeln("}"); + dot.writeln("}"); return numWritten; }