/** * Copyright (c) 2004-2011 Wang Jinbao(Julian Wong), http://www.ralasafe.com * Licensed under the MIT license: http://www.opensource.org/licenses/mit-license.php */ package org.ralasafe.db; import java.sql.Connection; import java.sql.DatabaseMetaData; import java.sql.ResultSet; import java.sql.ResultSetMetaData; import java.sql.SQLException; import java.sql.Statement; import java.util.ArrayList; import java.util.Collection; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.ralasafe.util.DBUtil; import org.ralasafe.util.StringUtil; /** * Reflect schema's table and view infos. * The table or view is omited which name starts with '$'. * We think it's a system table. * * @author back * */ public class DBView { private static final String[] tableType = new String[] { "TABLE" }; private static final String[] viewType = new String[] { "VIEW" }; private static final Log log=LogFactory.getLog( DBView.class ); public static String getDefaultSchema(String dsName) { Connection conn = DBPower.getConnection(dsName); try { return DBUtil.getDefaultSchema(conn); } catch (SQLException e) { log.error( "", e ); return ""; } finally { DBUtil.close(conn); } } public static TableView getTable(String dsName, String tableName) { Connection conn = null; try { conn = DBPower.getConnection(dsName); return getTable(conn, dsName, null, tableName); } catch (SQLException e) { log.error( "Failed to get definition of " + "table/view '" + tableName, e ); throw new DBLevelException(e); } finally { DBUtil.close(conn); } } public static TableView getTable(String dsName, String schema, String tableName) { Connection conn = null; try { conn = DBPower.getConnection(dsName); return getTable(conn, dsName, schema, tableName); } catch (SQLException e) { log.error( "Failed to get definition of " + "table/view '" + schema + "." + tableName, e ); throw new DBLevelException(e); } finally { DBUtil.close(conn); } } private static TableView getTable(Connection conn, String dsName, String schema, String tableName) throws SQLException { String mySchema = ""; if (!StringUtil.isEmpty(schema)) { mySchema = schema + "."; } if( log.isDebugEnabled() ) { log.debug( "Get table/view definition: dsName=" + dsName + ", table/view Name=" + mySchema+tableName ); } Statement stmt = null; ResultSet rs = null; ResultSet primaryKeys = null; try { stmt = conn.createStatement(); rs = stmt.executeQuery("select * from " + mySchema + tableName + " where 1=2"); ResultSetMetaData metaData = rs.getMetaData(); TableView table = new TableView(); table.setSchema(schema); table.setName(tableName); DatabaseMetaData metaData2 = conn.getMetaData(); String databaseProductName = DBUtil.getDatabaseProductName(conn); if (databaseProductName == DBUtil.MYSQL) { primaryKeys = metaData2.getPrimaryKeys(schema, null, tableName); } else { primaryKeys = metaData2.getPrimaryKeys(null, null, tableName); } Map pkColumnViewMap = new HashMap(); while (primaryKeys.next()) { pkColumnViewMap.put(primaryKeys.getString("COLUMN_NAME"), null); } List columnList = new ArrayList(metaData.getColumnCount()); for (int i = 1, columnCount = metaData.getColumnCount(); i <= columnCount; i++) { ColumnView column = new ColumnView(); String columnName = metaData.getColumnName(i); column.setName(columnName); String sqlType = metaData.getColumnTypeName(i); if (sqlType.equalsIgnoreCase("blob") || sqlType.equalsIgnoreCase("clob") || sqlType.equalsIgnoreCase("text")) { // DO NOTHING } else { int precision = metaData.getPrecision(i); int scale = metaData.getScale(i); if (precision != 0) { if (scale == 0) { sqlType = sqlType + "(" + precision + ")"; } else { sqlType = sqlType + "(" + precision + "," + scale + ")"; } } } column.setSqlType(sqlType); columnList.add(column); // it's a primary key? if (pkColumnViewMap.containsKey(columnName)) { pkColumnViewMap.put(columnName, column); } } table.setColumnViews(columnList); // sometimes, oracle jdbc driver returns pk info is redundance, // actually the column does exist at all. Clear them. clearInvalidPK(pkColumnViewMap); if (pkColumnViewMap.size() > 0) { table.setPkColumnViews(pkColumnViewMap.values()); } return table; } finally { DBUtil.close(primaryKeys); DBUtil.close(rs); DBUtil.close(stmt); } } private static void clearInvalidPK(Map pkColumnViewMap) { Iterator itr = pkColumnViewMap.entrySet().iterator(); while (itr.hasNext()) { Map.Entry entry = (Map.Entry) itr.next(); if (entry.getValue() == null) { itr.remove(); } } } public static String[] getSchemas(String dsName) { DataSource ds = DBPower.getDataSource(dsName); if (ds.isShowAllSchemas()) { return getAllSchemasFromDB(dsName); } else { return ds.getSchemas(); } } public static String[] getAllSchemasFromDB(String dsName) { Connection conn = null; ResultSet rs = null; try { conn = DBPower.getConnection(dsName); DatabaseMetaData metaData = conn.getMetaData(); String databaseProductName = DBUtil.getDatabaseProductName(conn); if (databaseProductName == DBUtil.MYSQL || databaseProductName == DBUtil.SQLSERVER) { rs = metaData.getCatalogs(); } else { rs = metaData.getSchemas(); } List result = new LinkedList(); while (rs.next()) { String name = rs.getString(1); result.add(name); } String[] names = new String[result.size()]; Iterator itr = result.iterator(); for (int i = 0; i < names.length; i++) { names[i] = (String) itr.next(); } return names; } catch (SQLException e) { log.error( "", e ); throw new DBLevelException(e); } finally { DBUtil.close(rs); DBUtil.close(conn); } } public static String[] getTableNames(String dsName, String schema) { return getObjectNames(dsName, schema, tableType); } private static String[] getObjectNames(String dsName, String schema, String[] objectTypes) { Connection conn = null; ResultSet tables = null; try { conn = DBPower.getConnection(dsName); DatabaseMetaData metaData = conn.getMetaData(); String databaseProductName = DBUtil.getDatabaseProductName(conn); if (databaseProductName == DBUtil.MYSQL || databaseProductName == DBUtil.SQLSERVER) { tables = metaData.getTables(schema, null, null, objectTypes); } else if (databaseProductName == DBUtil.ORACLE) { tables = metaData.getTables(null, null, null, objectTypes); } else { tables = metaData.getTables(null, schema, null, objectTypes); } List result = new LinkedList(); while (tables.next()) { String tableName = tables.getString("TABLE_NAME"); if (databaseProductName == DBUtil.ORACLE) { String s = tables.getString("TABLE_SCHEM"); if (s.equalsIgnoreCase(schema)) { result.add(tableName); } } else if (databaseProductName == DBUtil.SQLSERVER) { String s = tables.getString("TABLE_SCHEM"); tableName = s + "." + tableName; result.add(tableName); } else { result.add(tableName); } } String[] names = new String[result.size()]; Iterator itr = result.iterator(); for (int i = 0; i < names.length; i++) { names[i] = (String) itr.next(); } return names; } catch (SQLException e) { log.error( "", e ); throw new DBLevelException(e); } finally { DBUtil.close(tables); DBUtil.close(conn); } } public static Collection getTables(String dsName, String schema) { String[] tableNames = getTableNames(dsName, schema); return getTables(dsName, schema, tableNames); } public static Collection getTables(String dsName, String schema, String[] tableNames) { Connection conn = DBPower.getConnection(dsName); try { List tables = new ArrayList(); for (int i = 0; i < tableNames.length; i++) { // omit system tables like $sys_ if (tableNames[i].indexOf("$") >= 0) { continue; } try { TableView table = getTable(conn, dsName, schema, tableNames[i]); tables.add(table); } catch (SQLException e) { log.error( "Failed to get definition in schema '" + schema + "'." + "table/view:" + tableNames[i], e ); } } return tables; } finally { DBUtil.close(conn); } } public static String[] getViewNames(String dsName, String schema) { return getObjectNames(dsName, schema, viewType); } public static Collection getViewTables(String dsName, String schema, String[] viewNames) { return getTables(dsName, schema, viewNames); } public static Collection getViewTables(String dsName, String schema) { String[] viewNames = getViewNames(dsName, schema); return getTables(dsName, schema, viewNames); } }