Skip to content

Commit

Permalink
Refactored viewSql to viewDefinition, deprecated text in selectViewSQL
Browse files Browse the repository at this point in the history
* Optimized imports
* Refactored ViewService
* Switched from specified generic to implied (diamond)
* Added test for view and added selectViewSQL to h2
  • Loading branch information
npetzall committed Jan 21, 2018
1 parent 069d40d commit f73eb1c
Show file tree
Hide file tree
Showing 19 changed files with 197 additions and 72 deletions.
4 changes: 2 additions & 2 deletions docs/source/configuration/databaseType.rst
Expand Up @@ -145,7 +145,7 @@ So additional columns are ok, but you might need to alias columns so that they a
**selectRoutineParametersSql=**
specific_name, parameter_name, dtd_identifier, parameter_mode
**selectViewSql=**
view_definition, text
view_definition, text (text has been deprecated)
**selectCheckConstraintsSql=**
table_name, constraint_name
**selectTableIdsSql=**
Expand All @@ -157,6 +157,6 @@ So additional columns are ok, but you might need to alias columns so that they a
**selectColumnCommentsSql=**
table_name, column_name, comments

**Extend the types of views that exist**
**Define viewTypes**
**viewTypes=**
default is VIEW
31 changes: 11 additions & 20 deletions src/main/java/org/schemaspy/model/Table.java
Expand Up @@ -25,16 +25,7 @@
import org.slf4j.LoggerFactory;

import java.lang.invoke.MethodHandles;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.*;



Expand All @@ -50,12 +41,12 @@ public class Table implements Comparable<Table> {
private final String name;
private final String fullName;
private final String container;
protected CaseInsensitiveMap<TableColumn> columns = new CaseInsensitiveMap<TableColumn>();
private final List<TableColumn> primaryKeys = new ArrayList<TableColumn>();
private final CaseInsensitiveMap<ForeignKeyConstraint> foreignKeys = new CaseInsensitiveMap<ForeignKeyConstraint>();
private final CaseInsensitiveMap<TableIndex> indexes = new CaseInsensitiveMap<TableIndex>();
protected CaseInsensitiveMap<TableColumn> columns = new CaseInsensitiveMap<>();
private final List<TableColumn> primaryKeys = new ArrayList<>();
private final CaseInsensitiveMap<ForeignKeyConstraint> foreignKeys = new CaseInsensitiveMap<>();
private final CaseInsensitiveMap<TableIndex> indexes = new CaseInsensitiveMap<>();
private Object id;
private final Map<String, String> checkConstraints = new TreeMap<String, String>(String.CASE_INSENSITIVE_ORDER);
private final Map<String, String> checkConstraints = new TreeMap<>(String.CASE_INSENSITIVE_ORDER);
private long numRows;
protected final Database db;
private String comments;
Expand Down Expand Up @@ -240,7 +231,7 @@ public Map<String, String> getCheckConstraints() {
* @return
*/
public Set<TableIndex> getIndexes() {
return new HashSet<TableIndex>(indexes.values());
return new HashSet<>(indexes.values());
}

/**
Expand Down Expand Up @@ -301,9 +292,9 @@ public TableColumn getColumn(String columnName) {
* @return
*/
public List<TableColumn> getColumns() {
Set<TableColumn> sorted = new TreeSet<TableColumn>(new ByColumnIdComparator());
Set<TableColumn> sorted = new TreeSet<>(new ByColumnIdComparator());
sorted.addAll(columns.values());
return new ArrayList<TableColumn>(sorted);
return new ArrayList<>(sorted);
}

public void setColumns(CaseInsensitiveMap<TableColumn> columns) {
Expand Down Expand Up @@ -455,7 +446,7 @@ private ForeignKeyConstraint getSelfReferencingConstraint() {
* @return
*/
public List<ForeignKeyConstraint> removeNonRealForeignKeys() {
List<ForeignKeyConstraint> nonReals = new ArrayList<ForeignKeyConstraint>();
List<ForeignKeyConstraint> nonReals = new ArrayList<>();

for (TableColumn column : columns.values()) {
for (TableColumn parentColumn : column.getParents()) {
Expand Down Expand Up @@ -617,7 +608,7 @@ public boolean isRemote() {
* @return
* @see #isView()
*/
public String getViewSql() {
public String getViewDefinition() {
return null;
}

Expand Down
18 changes: 9 additions & 9 deletions src/main/java/org/schemaspy/model/View.java
Expand Up @@ -23,22 +23,22 @@
* defined them.
*/
public class View extends Table {
private String viewSql;
private String viewDefinition;

/**
* @param db
* @param catalog
* @param schema
* @param name
* @param remarks
* @param viewSql
* @param viewDefinition
*/
public View(Database db, String catalog, String schema,
String name, String remarks, String viewSql) {
String name, String remarks, String viewDefinition) {
super(db, catalog, schema, name, remarks);

if (viewSql != null && viewSql.trim().length() > 0)
this.viewSql = viewSql;
if (viewDefinition != null && viewDefinition.trim().length() > 0)
this.viewDefinition = viewDefinition;
}

/**
Expand All @@ -50,11 +50,11 @@ public boolean isView() {
}

@Override
public String getViewSql() {
return viewSql;
public String getViewDefinition() {
return viewDefinition;
}

public void setViewSql(String viewSql) {
this.viewSql = viewSql;
public void setViewDefinition(String viewDefinition) {
this.viewDefinition = viewDefinition;
}
}
Expand Up @@ -268,7 +268,7 @@ private void appendIndexes(Node tableNode, Table table) {
*/
private void appendView(Element tableNode, Table table) {
String sql;
if (table.isView() && (sql = table.getViewSql()) != null) {
if (table.isView() && (sql = table.getViewDefinition()) != null) {
DOMUtil.appendAttribute(tableNode, "viewSql", sql);
}
}
Expand Down
16 changes: 8 additions & 8 deletions src/main/java/org/schemaspy/service/DatabaseService.java
Expand Up @@ -166,12 +166,12 @@ private void initViews(Config config, Database db, ProgressListener listener, Da
for (BasicTableMeta entry : getBasicTableMeta(config, db, listener, metadata, false, types)) {
if (validator.isValid(entry.getName(), entry.getType())) {
View view = new View(db, entry.getCatalog(), entry.getSchema(), entry.getName(),
entry.getRemarks(), entry.getViewSql());
entry.getRemarks(), entry.getViewDefinition());

tableService.gatheringTableDetails(db, view);

if (entry.getViewSql() == null) {
view.setViewSql(viewService.fetchViewSql(db, view));
if (entry.getViewDefinition() == null) {
view.setViewDefinition(viewService.fetchViewDefinition(db, view));
}

db.getViewsMap().put(view.getName(), view);
Expand All @@ -192,7 +192,7 @@ private void initViews(Config config, Database db, ProgressListener listener, Da
*/
private String[] getTypes(Config config, String propName, String defaultValue) {
String value = config.getDbProperties().getProperty(propName, defaultValue);
List<String> types = new ArrayList<String>();
List<String> types = new ArrayList<>();
for (String type : value.split(",")) {
type = type.trim();
if (type.length() > 0)
Expand Down Expand Up @@ -313,7 +313,7 @@ void join() {
* Multi-threaded implementation of a class that creates tables
*/
private class ThreadedTableCreator extends TableCreator {
private final Set<Thread> threads = new HashSet<Thread>();
private final Set<Thread> threads = new HashSet<>();
private final int maxThreads;

ThreadedTableCreator(int maxThreads) {
Expand Down Expand Up @@ -393,7 +393,7 @@ private List<BasicTableMeta> getBasicTableMeta(Config config,
String... types) throws SQLException {
String queryName = forTables ? "selectTablesSql" : "selectViewsSql";
String sql = config.getDbProperties().getProperty(queryName);
List<BasicTableMeta> basics = new ArrayList<BasicTableMeta>();
List<BasicTableMeta> basics = new ArrayList<>();


if (sql != null) {
Expand All @@ -410,11 +410,11 @@ private List<BasicTableMeta> getBasicTableMeta(Config config,
if (cat == null && sch == null)
sch = db.getSchema().getName();
String remarks = getOptionalString(rs, clazz + "_comment");
String text = forTables ? null : getOptionalString(rs, "view_definition");
String viewDefinition = forTables ? null : getOptionalString(rs, "view_definition");
String rows = forTables ? getOptionalString(rs, "table_rows") : null;
long numRows = rows == null ? -1 : Long.parseLong(rows);

basics.add(new BasicTableMeta(cat, sch, name, clazz, remarks, text, numRows));
basics.add(new BasicTableMeta(cat, sch, name, clazz, remarks, viewDefinition, numRows));
}
} catch (SQLException sqlException) {
// don't die just because this failed
Expand Down
54 changes: 42 additions & 12 deletions src/main/java/org/schemaspy/service/ViewService.java
Expand Up @@ -10,6 +10,7 @@
import java.lang.invoke.MethodHandles;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.util.Objects;

Expand All @@ -23,6 +24,8 @@ public class ViewService {

private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());

private int deprecatedNagCounter = 0;

public ViewService(SqlService sqlService) {
this.sqlService = Objects.requireNonNull(sqlService);
}
Expand All @@ -33,27 +36,54 @@ public ViewService(SqlService sqlService) {
* @return
* @throws SQLException
*/
public String fetchViewSql(Database db, View view) throws SQLException {
public String fetchViewDefinition(Database db, View view) throws SQLException {
String selectViewSql = Config.getInstance().getDbProperties().getProperty("selectViewSql");
if (selectViewSql == null) {
return null;
}

StringBuilder viewDefinition = new StringBuilder();
try (PreparedStatement stmt = sqlService.prepareStatement(selectViewSql, db, view.getName());
ResultSet rs = stmt.executeQuery()) {

while (rs.next()) {
try {
viewDefinition.append(rs.getString("view_definition"));
} catch (SQLException tryOldName) {
viewDefinition.append(rs.getString("text"));
}
}
return viewDefinition.toString();
ResultSet resultSet = stmt.executeQuery()) {
return getViewDefinitionFromResultSet(resultSet);
} catch (SQLException sqlException) {
LOGGER.error(selectViewSql);
throw sqlException;
}
}

private String getViewDefinitionFromResultSet(ResultSet resultSet) throws SQLException {
if (isViewDefinitionColumnPresent(resultSet.getMetaData())) {
return getFromViewDefinitionColumn(resultSet);
}
return getFromTextColumn(resultSet);
}

private boolean isViewDefinitionColumnPresent(ResultSetMetaData resultSetMetaData) throws SQLException {
for(int i = 1; i <= resultSetMetaData.getColumnCount(); i++) {
if ("view_definition".equalsIgnoreCase(resultSetMetaData.getColumnLabel(i))){
return true;
}
}
return false;
}

private String getFromViewDefinitionColumn(ResultSet resultSet) throws SQLException {
StringBuilder viewDefinition = new StringBuilder();
while (resultSet.next()) {
viewDefinition.append(resultSet.getString("view_definition"));
}
return viewDefinition.toString();
}

private String getFromTextColumn(ResultSet resultSet) throws SQLException {
StringBuilder viewDefinition = new StringBuilder();
if (deprecatedNagCounter < 10) {
LOGGER.warn("ColumnLabel 'text' has been deprecated and will be removed");
deprecatedNagCounter++;
}
while (resultSet.next()) {
viewDefinition.append(resultSet.getString("text"));
}
return viewDefinition.toString();
}
}
12 changes: 6 additions & 6 deletions src/main/java/org/schemaspy/service/helper/BasicTableMeta.java
Expand Up @@ -13,25 +13,25 @@ public class BasicTableMeta
final String name;
final String type;
final String remarks;
final String viewSql;
final String viewDefinition;
final long numRows; // -1 if not determined

/**
* @param schema
* @param name
* @param type typically "TABLE" or "VIEW"
* @param remarks
* @param text optional textual SQL used to create the view
* @param viewDefinition optional textual SQL used to create the view
* @param numRows number of rows, or -1 if not determined
*/
public BasicTableMeta(String catalog, String schema, String name, String type, String remarks, String text, long numRows)
public BasicTableMeta(String catalog, String schema, String name, String type, String remarks, String viewDefinition, long numRows)
{
this.catalog = catalog;
this.schema = schema;
this.name = name;
this.type = type;
this.remarks = remarks;
viewSql = text;
this.viewDefinition = viewDefinition;
this.numRows = numRows;
}

Expand Down Expand Up @@ -59,7 +59,7 @@ public String getType() {
return type;
}

public String getViewSql() {
return viewSql;
public String getViewDefinition() {
return viewDefinition;
}
}
10 changes: 5 additions & 5 deletions src/main/java/org/schemaspy/view/HtmlTablePage.java
Expand Up @@ -105,15 +105,15 @@ public void writeMainTable(Database db, Table table, File outputDir, WriteStats
private Set<Table> sqlReferences(Table table, Database db) {
Set<Table> references = null;

if (table.isView() && table.getViewSql() != null) {
if (table.isView() && table.getViewDefinition() != null) {
DefaultSqlFormatter formatter = new DefaultSqlFormatter();
references = formatter.getReferencedTables(table.getViewSql(), db);
references = formatter.getReferencedTables(table.getViewDefinition(), db);
}
return references;
}

private String sqlCode(Table table) {
return table.getViewSql() != null ? table.getViewSql().trim() : "";
return table.getViewDefinition() != null ? table.getViewDefinition().trim() : "";
}

private Object indexExists(Table table, Set<MustacheTableIndex> indexedColumns) {
Expand All @@ -126,7 +126,7 @@ private Object indexExists(Table table, Set<MustacheTableIndex> indexedColumns)

private Object definitionExists(Table table) {
Object exists = null;
if (table.isView() && table.getViewSql() != null) {
if (table.isView() && table.getViewDefinition() != null) {
exists = new Object();
}
return exists;
Expand All @@ -141,7 +141,7 @@ private Object definitionExists(Table table) {
* two degrees of separation.
*
* @param table Table
* @param diagramsDir File
* @param diagramDir File
* @return boolean <code>true</code> if the table has implied relatives within two
* degrees of separation.
* @throws IOException
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/org/schemaspy/types/db2.properties
Expand Up @@ -14,7 +14,7 @@ driver=COM.ibm.db2.jdbc.app.DB2Driver
driverPath=c:/Program Files/IBM/SQLLIB/java/db2java.zip

# return text that represents a specific :view / :schema
selectViewSql=select text from syscat.views where viewname=:view and viewschema=:schema
selectViewSql=select text view_definition from syscat.views where viewname=:view and viewschema=:schema

# return table_name, constraint_name and text for a specific :schema
selectCheckConstraintsSql=select constname constraint_name, tabname table_name, text from syscat.checks where tabschema=:schema
Expand Down
2 changes: 1 addition & 1 deletion src/main/resources/org/schemaspy/types/db2zos.properties
Expand Up @@ -10,7 +10,7 @@ extends=db2
description=IBM DB2 for z/OS with the 'App' Driver

# return text that represents a specific :view / :schema
selectViewSql=select TEXT from SYSIBM.SYSVIEWS where NAME=:view and CREATOR=:schema
selectViewSql=select TEXT view_definition from SYSIBM.SYSVIEWS where NAME=:view and CREATOR=:schema

# return table_name, constraint_name and text for a specific :schema
selectCheckConstraintsSql=select CHECKNAME constraint_name, TBNAME table_name, CHECKCONDITION from SYSIBM.SYSCHECKS where TBOWNER=:schema
Expand Down
Expand Up @@ -10,7 +10,7 @@ extends=db2net
description=IBM DB2/zos with the Type 4 'Net' Driver

# return text that represents a specific :view / :schema
selectViewSql=select TEXT from SYSIBM.SYSVIEWS where NAME=:view and CREATOR=:schema
selectViewSql=select TEXT view_definition from SYSIBM.SYSVIEWS where NAME=:view and CREATOR=:schema

# return table_name, constraint_name and text for a specific :schema
selectCheckConstraintsSql=select CHECKNAME constraint_name, TBNAME table_name, CHECKCONDITION from SYSIBM.SYSCHECKS where TBOWNER=:schema
Expand Down

0 comments on commit f73eb1c

Please sign in to comment.