package com.med.sql; import java.io.PrintStream; import java.sql.*; import java.util.*; import javax.sql.DataSource; public class SchemaChecker { public static boolean checkSchemas(DataSource dataSource, String nameSpace, DbmsInfo.Product dbms, PrintStream out) { boolean ok = true; String[] tableTypes = { "TABLE" }; Connection cn = null; try { cn = dataSource.getConnection(); DatabaseMetaData dbmd = cn.getMetaData(); ok = checkSchemaNames(cn, dbmd, tableTypes, nameSpace, dbms, out); } catch (Exception e) { e.printStackTrace(); } finally { try { cn.close(); } catch (SQLException e) { } cn = null; } return ok; } static boolean checkSchemaNames(Connection cn, DatabaseMetaData dbmd, String[] tableTypes, String nameSpace, DbmsInfo.Product dbms, PrintStream out)throws SQLException { boolean debug = false; boolean okay = true; HashSet<String> uniqueNames = new HashSet<String>(); ResultSet rsSchemas = dbmd.getSchemas(); while (rsSchemas.next()) { String schemaName = rsSchemas.getString(1); if (dbms.equals(DbmsInfo.Product.ORACLE) && OracleUtils.isOracleSchema(schemaName)) continue; // if (dbms.equals(DbmsInfo.Product.CACHE) && CacheUtils.isCacheSchema(schemaName)) // continue; if (debug) System.out.println("Schema: "+schemaName); if (!OracleUtils.isValidLength(schemaName)) { out.println( "Schema id: " + schemaName + " is "+schemaName.length()+" bytes long."); okay = false; } if (OracleUtils.isReservedWord(schemaName)) { out.println( "Schema id: " + schemaName + " is an Oracle reserved word."); okay = false; } ResultSet rsTable = dbmd.getTables(nameSpace, schemaName, "%", tableTypes); // check table names for the schema while (rsTable.next()) { String tableName = rsTable.getString("TABLE_NAME"); //out.println("Table id: "+tableName+" Table id: "+schemaName + "." + tableName); if (!uniqueNames.contains(tableName)) uniqueNames.add(tableName); else { out.println( "WARNING Table id: " + tableName + " is not unique across schemas."); //okay = false; } if (!OracleUtils.isValidLength(tableName)) { out.println( "Table id: " + schemaName + "." + tableName + " is "+tableName.length()+" bytes long."); okay = false; } if (OracleUtils.isReservedWord(tableName)) { out.println( "Table id: " + schemaName + "." + tableName + " is an Oracle reserved word."); okay = false; } // check column names for the table ResultSet rsColumn = dbmd.getColumns(schemaName, null, tableName, "%"); while (rsColumn.next()) { String columnName = rsColumn.getString("COLUMN_NAME"); if (!OracleUtils.isValidLength(columnName)) { out.println( "Column id: " + columnName + " ("+ schemaName + "." + tableName + "." + columnName + " is "+columnName.length()+" bytes long."); okay = false; } if (OracleUtils.isReservedWord(columnName)) { out.println( "Column id: " + schemaName + "." + tableName + "." + columnName + " is an Oracle reserved word."); okay = false; } } rsColumn.close(); // check primary key name for the table ResultSet rsPrimaryKey = dbmd.getPrimaryKeys(null, schemaName, tableName); // boolean hasPrimaryKey = false; while (rsPrimaryKey.next()) { // hasPrimaryKey = true; String keyName = rsPrimaryKey.getString("PK_NAME"); short seqNumber = rsPrimaryKey.getShort("KEY_SEQ"); if ("IDKEYField_As_PKey".equals(keyName)) continue; // Cache's default PK for the IDENTITY column if no PK spec'd if (!uniqueNames.contains(keyName)) uniqueNames.add(keyName); else if (seqNumber == 1){ out.println( "WARNING Primary key id: " + keyName + " is not unique across schemas."); //okay = false; } if (!OracleUtils.isValidLength(keyName)) { out.println( "Primary key id: " + schemaName + "." + tableName + "." + keyName + " is "+keyName.length()+" bytes long."); okay = false; } if (OracleUtils.isReservedWord(keyName)) { out.println( "Primary key id: " + schemaName + "." + tableName + "." + keyName + " is an Oracle reserved word."); okay = false; } } rsPrimaryKey.close(); // if (!hasPrimaryKey) { // out.println( // "WARNING Table: " + schemaName + "." + tableName + " does not define a primary key."); // //okay = false; // } // check foreign key names for the table ResultSet rsForeignKey = dbmd.getImportedKeys(null, schemaName, tableName); while (rsForeignKey.next()) { String keyName = rsForeignKey.getString("FK_NAME"); short seqNumber = rsForeignKey.getShort("KEY_SEQ"); // short updateRule = rsForeignKey.getShort("UPDATE_RULE"); // short deleteRule = rsForeignKey.getShort("DELETE_RULE"); // if (debug) { // System.out.println("checking fk: "+keyName+", seqNumber="+seqNumber); // if (deleteRule != DatabaseMetaData.importedKeyNoAction ) // System.out.println("FK: " + keyName + " delete rule="+getDeleteRule(deleteRule)); // } if (!uniqueNames.contains(keyName)) uniqueNames.add(keyName); else if (seqNumber == 1){ if (debug) { System.out.println("Current schema names:"); for (String s : uniqueNames) { System.out.println("\t"+s); } } out.println( "WARNING Foreign key id: " + keyName + " is not unique across schemas."); //okay = false; } if (!OracleUtils.isValidLength(keyName)) { out.println( "Foreign key id: " + schemaName + "." + tableName + "." + keyName + " is "+keyName.length()+" bytes long."); okay = false; } if (OracleUtils.isReservedWord(keyName)) { out.println( "Foreign key id: " + schemaName + "." + tableName + "." + keyName + " is an Oracle reserved word."); okay = false; } } rsForeignKey.close(); // // check unique index names for the table // ResultSet rsUniqueIndices = dbmd.getIndexInfo(nameSpace, schemaName, tableName, true, true); // HashSet<String> uniqueIndexNames = new HashSet<String>(); // String oldIndexName = "xxxxjunkxxx"; // while (rsUniqueIndices.next()) { // if (rsUniqueIndices.getString("INDEX_NAME") != null) { // if (!oldIndexName.equals(rsUniqueIndices.getString("INDEX_NAME"))) { // String indexName = rsUniqueIndices.getString("INDEX_NAME"); // // if (!uniqueIndexNames.contains(indexName)) // uniqueIndexNames.add(indexName); // // if (!uniqueNames.contains(indexName)) // uniqueNames.add(indexName); // else { // if (debug) { // System.out.println("Current schema names:"); // for (String s : uniqueNames) { // System.out.println("\t"+s); // } // } // out.println( // "WARNING Unique Index id: " + indexName + " is not unique across schemas."); // //okay = false; // } // // if (!OracleUtils.isValidLength(indexName)) { // out.println( // "Unique Index id: " + schemaName + "." + tableName + "." + indexName + " is "+indexName.length()+" bytes long."); // okay = false; // } // if (OracleUtils.isReservedWord(indexName)) { // out.println( // "Unique Index id: " + schemaName + "." + tableName + "." + indexName + " is an Oracle reserved word."); // okay = false; // } // oldIndexName = indexName; // } // } // if index not null // } // while indices // rsUniqueIndices.close(); // // // check non-unique index names for the table // ResultSet rsIndices = dbmd.getIndexInfo(nameSpace, schemaName, tableName, false, true); // // oldIndexName = "xxxxjunkxxx"; // while (rsIndices.next()) { // if (rsIndices.getString("INDEX_NAME") != null) { // if (!oldIndexName.equals(rsIndices.getString("INDEX_NAME"))) { // String indexName = rsIndices.getString("INDEX_NAME"); // // if (uniqueIndexNames.contains(indexName)) // continue; // // if (!uniqueNames.contains(indexName)) // uniqueNames.add(indexName); // else { // if (debug) { // System.out.println("Current schema names:"); // for (String s : uniqueNames) { // System.out.println("\t"+s); // } // } // out.println( // "WARNING Non-unique Index id: " + indexName + " is not unique across schemas."); // //okay = false; // } // // if (!OracleUtils.isValidLength(indexName)) { // out.println( // "Non-unique Index id: " + schemaName + "." + tableName + "." + indexName + " is "+indexName.length()+" bytes long."); // okay = false; // } // if (OracleUtils.isReservedWord(indexName)) { // out.println( // "Non-unique Index id: " + schemaName + "." + tableName + "." + indexName + " is an Oracle reserved word."); // okay = false; // } // oldIndexName = indexName; // } // // } // if index not null // } // while indices // rsIndices.close(); // check trigger names for the table List<String> triggerNames = getTriggerNames(cn, schemaName, tableName, dbms); for (String triggerName : triggerNames) { if (!uniqueNames.contains(triggerName)) uniqueNames.add(triggerName); else { if (debug) { System.out.println("Current schema names:"); for (String s : uniqueNames) { System.out.println("\t"+s); } } out.println( "WARNING Trigger id: " + triggerName + " is not unique across schemas."); //okay = false; } if (!OracleUtils.isValidLength(triggerName)) { out.println( "Trigger id: " + triggerName + "." + tableName + "." + triggerName + " is "+triggerName.length()+" bytes long."); okay = false; } if (OracleUtils.isReservedWord(triggerName)) { out.println( "Trigger id: " + schemaName + "." + tableName + "." + triggerName + " is an Oracle reserved word."); okay = false; } } } // while table rsTable.close(); } rsSchemas.close(); return okay; } static List<String> getTriggerNames(Connection cn, String schemaName, String tableName, DbmsInfo.Product dbms) { List<String> triggerNames = new ArrayList<String>(); if (dbms.equals(DbmsInfo.Product.CACHE)) { java.sql.Statement statement = null; try { // SELECT parent , Event , Origin , SqlName , _Time // FROM %Dictionary.CompiledTrigger where parent='TASKLIST.TASK' String sql = "SELECT parent, Event, Origin, SqlName, _Time "+ "FROM %Dictionary.CompiledTrigger where parent='"+schemaName+"."+tableName+"'"; statement = cn.createStatement(); ResultSet results = statement.executeQuery(sql); while (results.next()) { String triggerName = results.getString("SqlName"); triggerNames.add(triggerName); } statement.close(); } catch (SQLException e) { e.printStackTrace(); } } return triggerNames; } static String getDeleteRule(short rule) { String s = null; if (rule == DatabaseMetaData.importedKeySetDefault ) s = "importedKeySetDefault "; else if (rule == DatabaseMetaData.importedKeySetNull ) s = "importedKeySetNull"; else if (rule == DatabaseMetaData.importedKeyCascade ) s = "importedKeyCascade"; else if (rule == DatabaseMetaData.importedKeyRestrict ) s = "importedKeyRestrict"; else if (rule == DatabaseMetaData.importedKeySetNull ) s = "importedKeySetNull"; return s; } }