package org.beanfuse.db.meta; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.SQLException; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Iterator; import java.util.List; import java.util.Map; import org.apache.commons.lang.StringUtils; import org.beanfuse.db.dialect.Dialect; import org.slf4j.Logger; import org.slf4j.LoggerFactory; /** * JDBC table metadata * * @author chaostone */ public class TableMetadata { private static final Logger logger = LoggerFactory.getLogger(TableMetadata.class); private String catalog; private String schema; private String name; private Map<String, ColumnMetadata> columns = new HashMap(); private Map foreignKeys = new HashMap(); private Map indexes = new HashMap(); public TableMetadata() { super(); } public TableMetadata(ResultSet rs, DatabaseMetaData meta, boolean extras) throws SQLException { catalog = rs.getString("TABLE_CAT"); schema = rs.getString("TABLE_SCHEM"); name = rs.getString("TABLE_NAME"); initColumns(meta); if (extras) { initForeignKeys(meta); initIndexes(meta); } logger.debug("table found:{} {} ", qualify(catalog, schema, name), columns.keySet()); if (extras) { logger.debug("foreign keys: {}", foreignKeys.keySet()); logger.debug("indexes: {}", indexes.keySet()); } } public String[] getColumnNames() { List<ColumnMetadata> columnList = new ArrayList<ColumnMetadata>(columns.values()); Collections.sort(columnList); List<String> columnNames = new ArrayList(columnList.size()); for (ColumnMetadata column : columnList) { columnNames.add(column.getName()); } return columnNames.toArray(new String[columnList.size()]); } public String identifier() { return qualify(catalog, schema, name); } public static String qualify(String catalog, String schema, String table) { StringBuffer qualifiedName = new StringBuffer(); if (catalog != null) { qualifiedName.append(catalog).append('.'); } if (schema != null) { qualifiedName.append(schema).append('.'); } return qualifiedName.append(table).toString(); } public String sqlInsertString() { String[] columnNames = getColumnNames(); StringBuffer sb = new StringBuffer("insert into "); sb.append(identifier()).append("("); for (int i = 0; i < columnNames.length; i++) { sb.append(columnNames[i]).append(','); } sb.setCharAt(sb.length() - 1, ')'); sb.append(" values("); sb.append(StringUtils.repeat("?,", columnNames.length)); sb.setCharAt(sb.length() - 1, ')'); return sb.toString(); } public String sqlCreateString(Dialect dialect) { StringBuffer buf = new StringBuffer(dialect.getCreateTableString()).append(' ').append( identifier()).append(" ("); Iterator iter = columns.values().iterator(); while (iter.hasNext()) { ColumnMetadata col = (ColumnMetadata) iter.next(); buf.append(col.getName()).append(' '); buf.append(col.getSqlType(dialect)); // String defaultValue = col.getDefaultValue(); // if (defaultValue != null) { // buf.append(" default ").append(defaultValue); // } // if (col.isNullable()) { // buf.append(dialect.getNullColumnString()); // } else { // buf.append(" not null"); // } // boolean useUniqueConstraint = col.isUnique() // && (!col.isNullable() || dialect.supportsNotNullUnique()); // if (useUniqueConstraint) { // if (dialect.supportsUnique()) { // buf.append(" unique"); // } else { // UniqueKey uk = getOrCreateUniqueKey(col.getQuotedName(dialect) + // '_'); // uk.addColumn(col); // } // } // // if (col.hasCheckConstraint() && dialect.supportsColumnCheck()) { // buf.append(" check (").append(col.getCheckConstraint()).append(")"); // } // // String columnComment = col.getComment(); // if (columnComment != null) { // buf.append(dialect.getColumnComment(columnComment)); // } if (iter.hasNext()) { buf.append(", "); } } buf.append(')'); return buf.toString(); } public String getName() { return name; } public String getCatalog() { return catalog; } public String getSchema() { return schema; } public void setSchema(String schema) { this.schema = schema; } public void setName(String name) { this.name = name; } public Map getColumns() { return columns; } public String toString() { return qualify(catalog, schema, name); } public ColumnMetadata getColumnMetadata(String columnName) { return (ColumnMetadata) columns.get(columnName.toLowerCase()); } public ForeignKeyMetadata getForeignKeyMetadata(String keyName) { return (ForeignKeyMetadata) foreignKeys.get(keyName.toLowerCase()); } public IndexMetadata getIndexMetadata(String indexName) { return (IndexMetadata) indexes.get(indexName.toLowerCase()); } private void addForeignKey(ResultSet rs) throws SQLException { String fk = rs.getString("FK_NAME"); if (fk == null) return; ForeignKeyMetadata info = getForeignKeyMetadata(fk); if (info == null) { info = new ForeignKeyMetadata(rs); foreignKeys.put(info.getName().toLowerCase(), info); } info.addColumn(getColumnMetadata(rs.getString("FKCOLUMN_NAME"))); } private void addIndex(ResultSet rs) throws SQLException { String index = rs.getString("INDEX_NAME"); if (index == null) return; IndexMetadata info = getIndexMetadata(index); if (info == null) { info = new IndexMetadata(rs); indexes.put(info.getName().toLowerCase(), info); } info.addColumn(getColumnMetadata(rs.getString("COLUMN_NAME"))); } public void addColumn(ResultSet rs) throws SQLException { String column = rs.getString("COLUMN_NAME"); if (column == null) return; if (getColumnMetadata(column) == null) { ColumnMetadata info = new ColumnMetadata(rs); columns.put(info.getName().toLowerCase(), info); } } private void initForeignKeys(DatabaseMetaData meta) throws SQLException { ResultSet rs = null; try { rs = meta.getImportedKeys(catalog, schema, name); while (rs.next()) addForeignKey(rs); } finally { if (rs != null) rs.close(); } } private void initIndexes(DatabaseMetaData meta) throws SQLException { ResultSet rs = null; try { rs = meta.getIndexInfo(catalog, schema, name, false, true); while (rs.next()) { if (rs.getShort("TYPE") == DatabaseMetaData.tableIndexStatistic) continue; addIndex(rs); } } finally { if (rs != null) rs.close(); } } private void initColumns(DatabaseMetaData meta) throws SQLException { ResultSet rs = null; try { rs = meta.getColumns(catalog, schema, name, "%"); while (rs.next()) addColumn(rs); } finally { if (rs != null) rs.close(); } } }