1 21 22 package org.apache.derby.tools; 23 24 import java.io.BufferedReader ; 25 import java.io.StringReader ; 26 27 import java.sql.DriverManager ; 28 import java.sql.ResultSet ; 29 import java.sql.Connection ; 30 import java.sql.Statement ; 31 import java.sql.PreparedStatement ; 32 import java.sql.SQLException ; 33 import java.sql.SQLWarning ; 34 import java.sql.Timestamp ; 35 36 import java.util.HashMap ; 37 import java.util.StringTokenizer ; 38 import java.util.ArrayList ; 39 40 import org.apache.derby.iapi.tools.i18n.LocalizedResource; 41 42 import org.apache.derby.impl.tools.dblook.DB_Check; 43 import org.apache.derby.impl.tools.dblook.DB_Index; 44 import org.apache.derby.impl.tools.dblook.DB_Jar; 45 import org.apache.derby.impl.tools.dblook.DB_Key; 46 import org.apache.derby.impl.tools.dblook.DB_Table; 47 import org.apache.derby.impl.tools.dblook.DB_Schema; 48 import org.apache.derby.impl.tools.dblook.DB_Alias; 49 import org.apache.derby.impl.tools.dblook.DB_Trigger; 50 import org.apache.derby.impl.tools.dblook.DB_View; 51 import org.apache.derby.impl.tools.dblook.DB_GrantRevoke; 52 import org.apache.derby.impl.tools.dblook.Logs; 53 54 public final class dblook { 55 56 private static final int DB2_MAX_NUMBER_OF_TABLES = 30; 59 60 private Connection conn; 61 private static PreparedStatement getColNameFromNumberQuery; 62 63 private static HashMap schemaMap; 66 private static HashMap tableIdToNameMap; 67 68 private static String sourceDBUrl; 70 private static String ddlFileName; 71 private static String stmtDelimiter; 72 private static boolean appendLogs; 73 private static ArrayList tableList; 74 private static String schemaParam; 75 private static String targetSchema; 76 private static boolean skipViews; 77 private static boolean verbose; 78 private static String sourceDBName; 79 80 private static String lookLogName = "dblook.log"; 81 82 private static LocalizedResource langUtil; 83 84 private static boolean sqlAuthorization; 85 86 91 92 public static void main(String [] args) { 93 94 try { 95 new dblook(args); 96 } catch (Exception e) { 97 e.printStackTrace(); 102 } 103 104 } 105 106 112 113 public dblook(String [] args) throws Exception { 114 115 langUtil = LocalizedResource.getInstance(); 118 119 initState(); 121 122 if (!parseArgs(args)) { 124 System.out.println(lookupMessage("DBLOOK_Usage")); 125 return; 126 } 127 128 showVariables(); 129 130 if (!loadDriver()) { 131 return; 134 } 135 136 schemaMap = new HashMap (); 137 tableIdToNameMap = new HashMap (); 138 139 go(); 141 142 } 143 144 148 149 private void initState() { 150 151 sourceDBUrl = null; 152 ddlFileName = null; 153 stmtDelimiter = null; 154 appendLogs = false; 155 tableList = null; 156 targetSchema = null; 157 schemaParam = null; 158 skipViews = false; 159 verbose= false; 160 sourceDBName = null; 161 return; 162 163 } 164 165 172 173 private boolean parseArgs(String [] args) { 174 175 if (args.length < 2) 176 return false; 178 179 int st = 0; 180 for (int i = 0; i < args.length; i++) { 181 st = loadParam(args, i); 182 if (st == -1) 183 return false; 184 i = st; 185 } 186 187 if (sourceDBUrl == null) { 188 return false; 190 } 191 192 196 boolean okay = Logs.initLogs(lookLogName, ddlFileName, appendLogs, 198 verbose, (stmtDelimiter == null ? ";" : stmtDelimiter)); 199 200 sourceDBName = extractDBNameFromUrl(sourceDBUrl); 202 203 if ((schemaParam != null) && (schemaParam.length() > 0) && 205 (schemaParam.charAt(0) != '"')) 206 { 208 targetSchema = addQuotes(expandDoubleQuotes( 209 schemaParam.toUpperCase(java.util.Locale.ENGLISH))); 210 } 211 else 212 targetSchema = addQuotes(expandDoubleQuotes(stripQuotes(schemaParam))); 213 return okay; 214 215 } 216 217 225 226 private int loadParam(String [] args, int start) { 227 228 if ((args[start].length() == 0) || args[start].charAt(0) != '-') 229 return start; 232 233 boolean haveVal = (args.length > start + 1); 234 switch (args[start].charAt(1)) { 235 236 case 'd': 237 if (!haveVal) 238 return -1; 239 if (args[start].length() == 2) { 240 sourceDBUrl = stripQuotes(args[++start]); 241 return start; 242 } 243 return -1; 244 245 case 'z': 246 if (!haveVal) 247 return -1; 248 if (args[start].length() == 2) { 249 schemaParam = args[++start]; 250 return start; 251 } 252 return -1; 253 254 case 't': 255 if (!haveVal) 256 return -1; 257 if (args[start].equals("-td")) { 258 stmtDelimiter = args[++start]; 259 return start; 260 } 261 else if (args[start].equals("-t")) 262 return extractTableNamesFromList(args, start+1); 264 return -1; 265 266 case 'o': 267 if (!haveVal) 268 return -1; 269 if ((args[start].length() == 2) && (args[start+1].length() > 0)) { 270 ddlFileName = args[++start]; 271 return start; 272 } 273 return -1; 274 275 case 'a': 276 if (args[start].equals("-append")) { 277 appendLogs = true; 278 return start; 279 } 280 return -1; 281 282 case 'n': 283 if (args[start].equals("-noview")) { 284 skipViews = true; 285 return start; 286 } 287 return -1; 288 289 case 'v': 290 if (args[start].equals("-verbose")) { 291 verbose = true; 292 return start; 293 } 294 return -1; 295 296 default: 297 return -1; 298 299 } 300 301 } 302 303 309 310 private boolean loadDriver() { 311 312 String derbyDriver = System.getProperty("driver"); 313 if (derbyDriver == null) { 314 if (sourceDBUrl.indexOf(":net://") != -1) 315 derbyDriver = "com.ibm.db2.jcc.DB2Driver"; 316 else if (sourceDBUrl.startsWith("jdbc:derby://")) 317 derbyDriver = "org.apache.derby.jdbc.ClientDriver"; 318 else 319 derbyDriver = "org.apache.derby.jdbc.EmbeddedDriver"; 320 } 321 322 try { 323 Class.forName(derbyDriver).newInstance(); 324 } 325 catch (Exception e) 326 { 327 Logs.debug(e); 328 return false; 329 } 330 331 return true; 332 } 333 334 345 346 private String extractDBNameFromUrl(String dbUrl) { 347 348 if (dbUrl == null) 349 return ""; 352 353 int start = dbUrl.indexOf("jdbc:derby:"); 354 if (start == -1) 355 return ""; 358 359 start = dbUrl.indexOf("://"); 360 if (start == -1) 361 start = dbUrl.indexOf("derby:") + 6; 365 else 366 start = dbUrl.indexOf("/", start+3) + 1; 371 372 int stop = -1; 373 if (dbUrl.charAt(start) == '"') { 374 start++; 377 stop = dbUrl.indexOf("\"", start); 378 } 379 else { 380 stop = dbUrl.indexOf(":", start); 384 if (stop != -1) { 385 if ((dbUrl.charAt(stop+1) == '/') || 386 (dbUrl.charAt(stop+1) == '\\')) 387 stop = dbUrl.indexOf(":", stop+2); 390 } 391 int stop2 = dbUrl.length(); 392 if (stop == -1) 393 stop = dbUrl.indexOf(";", start); 395 else 396 stop2 = dbUrl.indexOf(";", start); 397 stop = (stop <= stop2 ? stop : stop2); 398 } 399 400 if (stop == -1) 401 stop = dbUrl.length(); 404 405 return dbUrl.substring(start, stop); 406 407 } 408 409 426 427 private int extractTableNamesFromList(String [] args, 428 int start) 429 { 430 431 int argIndex = start; 432 int count = 0; 433 tableList = new ArrayList (); 434 while (argIndex < args.length) { 435 436 if (((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '-')) || 437 (++count > DB2_MAX_NUMBER_OF_TABLES)) 438 break; 440 441 if ((args[argIndex].length() > 0) && (args[argIndex].charAt(0) == '"')) 442 tableList.add(addQuotes(expandDoubleQuotes( 444 stripQuotes(args[argIndex++])))); 445 else 446 tableList.add(addQuotes( 449 expandDoubleQuotes(args[argIndex++].toUpperCase( 450 java.util.Locale.ENGLISH)))); 451 452 } 453 454 if (tableList.size() == 0) 455 tableList = null; 456 457 return argIndex - 1; 458 459 } 460 461 466 467 private void showVariables() { 468 469 if (ddlFileName != null) { 470 Logs.reportString("============================\n"); 471 Logs.reportMessage("DBLOOK_FileCreation"); 472 if (verbose) 473 writeVerboseOutput("DBLOOK_OutputLocation", 474 ddlFileName); 475 } 476 477 Logs.reportMessage("DBLOOK_Timestamp", 478 new Timestamp (System.currentTimeMillis()).toString()); 479 Logs.reportMessage("DBLOOK_DBName", sourceDBName); 480 Logs.reportMessage("DBLOOK_DBUrl", sourceDBUrl); 481 if (tableList != null) 482 Logs.reportMessage("DBLOOK_TargetTables"); 483 if (schemaParam != null) 484 Logs.reportMessage("DBLOOK_TargetSchema", stripQuotes(schemaParam)); 485 Logs.reportString("appendLogs: " + appendLogs + "\n"); 486 return; 487 488 } 489 490 506 507 private void go() 508 throws Exception 509 { 510 511 try 512 { 513 this.conn = DriverManager.getConnection(sourceDBUrl); 516 prepForDump(); 517 518 520 DB_Schema.doSchemas(this.conn, 523 (tableList != null) && (targetSchema == null)); 524 525 if (tableList == null) { 526 DB_Jar.doJars(sourceDBName, this.conn); 528 DB_Alias.doProceduresAndFunctions(this.conn); 529 } 530 531 DB_Table.doTables(this.conn, tableIdToNameMap); 532 DB_Index.doIndexes(this.conn); 533 DB_Alias.doSynonyms(this.conn); 534 DB_Key.doKeys(this.conn); 535 DB_Check.doChecks(this.conn); 536 537 if (!skipViews) 538 DB_View.doViews(this.conn); 539 540 DB_Trigger.doTriggers(this.conn); 541 542 DB_GrantRevoke.doAuthorizations(this.conn); 543 544 if (getColNameFromNumberQuery != null) 546 getColNameFromNumberQuery.close(); 547 Logs.cleanup(); 548 549 } 550 catch (SQLException sqlE) 551 { 552 Logs.debug(sqlE); 553 Logs.debug(Logs.unRollExceptions(sqlE), (String )null); 554 Logs.cleanup(); 555 return; 556 } 557 catch (Exception e) 558 { 559 Logs.debug(e); 560 Logs.cleanup(); 561 return; 562 } 563 finally { 564 if (conn != null) { 566 conn.commit(); 567 conn.close(); 568 } 569 } 570 571 } 572 573 579 580 private void prepForDump() throws Exception { 581 582 this.conn.setAutoCommit(false); 586 587 getColNameFromNumberQuery = conn.prepareStatement( 589 "SELECT COLUMNNAME FROM SYS.SYSCOLUMNS WHERE " + 590 "REFERENCEID = ? AND COLUMNNUMBER = ?"); 591 592 Statement stmt = conn.createStatement(); 594 ResultSet rs = stmt.executeQuery("SELECT T.TABLEID, T.TABLENAME, " + 595 "S.SCHEMANAME FROM SYS.SYSTABLES T, SYS.SYSSCHEMAS S " + 596 "WHERE T.TABLETYPE = 'T' AND T.SCHEMAID = S.SCHEMAID"); 597 598 while (rs.next()) { 599 String tableName = addQuotes(expandDoubleQuotes(rs.getString(2))); 600 String schemaName = addQuotes(expandDoubleQuotes(rs.getString(3))); 601 tableIdToNameMap.put(rs.getString(1), 602 schemaName + "." + tableName); 603 } 604 605 rs = stmt.executeQuery("SELECT SCHEMAID, SCHEMANAME FROM " + 607 "SYS.SYSSCHEMAS"); 608 while (rs.next()) { 609 schemaMap.put(rs.getString(1), 610 addQuotes(expandDoubleQuotes(rs.getString(2)))); 611 } 612 613 rs = stmt.executeQuery("VALUES SYSCS_UTIL.SYSCS_GET_DATABASE_PROPERTY" + 616 "('derby.database.sqlAuthorization')"); 617 if (rs.next()) 618 { 619 String sqlAuth = rs.getString(1); 620 if (Boolean.valueOf(sqlAuth).booleanValue()) 621 sqlAuthorization = true; 622 } 623 stmt.close(); 624 625 return; 627 628 } 629 630 647 648 public static String getColumnListFromDescription(String tableId, 649 String description) throws SQLException 650 { 651 652 StringBuffer sb = new StringBuffer (); 653 StringTokenizer tokenizer = new StringTokenizer ( 654 description.substring(description.indexOf("(") + 1, 655 description.lastIndexOf(")")), " ,", true); 656 657 boolean firstCol = true; 658 while (tokenizer.hasMoreTokens()) { 659 660 String tok = tokenizer.nextToken().trim(); 661 if (tok.equals("")) 662 continue; 663 else if (tok.equals(",")) { 664 firstCol = false; 665 continue; 666 } 667 try { 668 String colName = getColNameFromNumber(tableId, 669 (Integer.valueOf(tok)).intValue()); 670 if (!firstCol) 671 sb.append(", "); 672 sb.append(colName); 673 } catch (NumberFormatException e) { 674 tok = tok.toUpperCase(); 677 if (tok.equals("DESC") || tok.equals("ASC")) 678 sb.append(" " + tok); 680 else 681 Logs.debug("INTERNAL ERROR: read a non-number (" + 683 tok + ") when a column number was expected:\n" + 684 description, (String )null); 685 } 686 687 } 688 689 return sb.toString(); 690 691 } 692 693 704 705 public static String getColNameFromNumber(String tableId, 706 int colNum) throws SQLException 707 { 708 709 getColNameFromNumberQuery.setString(1, tableId); 710 getColNameFromNumberQuery.setInt(2, colNum); 711 ResultSet rs = getColNameFromNumberQuery.executeQuery(); 712 713 if (!rs.next()) { 714 Logs.debug("INTERNAL ERROR: Failed column number " + 716 "lookup for table " + lookupTableId(tableId) + 717 ", column " + colNum, (String )null); 718 rs.close(); 719 return ""; 720 } 721 else { 722 String colName = addQuotes(expandDoubleQuotes(rs.getString(1))); 723 rs.close(); 724 return colName; 725 } 726 727 } 728 729 736 737 public static String addQuotes(String name) { 738 739 if (name == null) 740 return null; 741 742 return "\"" + name + "\""; 743 744 } 745 746 747 public static String addSingleQuotes(String name) { 748 749 if (name == null) 750 return null; 751 752 return "'" + name + "'"; 753 } 754 755 766 767 public static String stripQuotes(String quotedName) { 768 769 if (quotedName == null) 770 return null; 771 772 if (!(quotedName.startsWith("'") || quotedName.startsWith("\""))) 773 return quotedName; 775 776 if (!(quotedName.endsWith("'") || quotedName.endsWith("\""))) 777 return quotedName; 779 780 return quotedName.substring(1, quotedName.length() - 1); 782 783 } 784 785 797 798 public static boolean isExcludedTable(String tableName) { 799 800 if (tableName == null) 801 return true; 802 803 int dot = tableName.indexOf("."); 804 if (dot != -1) { 805 if (isIgnorableSchema(tableName.substring(0, dot))) 808 return true; 810 tableName = tableName.substring(dot + 1, 811 tableName.length()); 812 } 813 814 return ((tableList != null) && !tableList.contains(tableName)); 815 816 } 817 818 829 830 private static final String [] ignorableSchemaNames = { 831 "SYSIBM", 832 "SYS", 833 "SYSVISUAL", 834 "SYSCAT", 835 "SYSFUN", 836 "SYSPROC", 837 "SYSSTAT", 838 "NULLID", 839 "SYSCS_ADMIN", 840 "SYSCS_DIAG", 841 "SYSCS_UTIL", 842 "SQLJ"}; 843 844 public static boolean isIgnorableSchema(String schemaName) { 845 846 if ((targetSchema != null) && (!schemaName.equals(targetSchema))) 847 return true; 848 849 schemaName = stripQuotes(schemaName); 850 851 boolean ret = false; 852 853 for (int i = ignorableSchemaNames.length - 1; i >= 0;) 854 { 855 if ((ret = ignorableSchemaNames[i--].equalsIgnoreCase(schemaName))) 856 break; 857 } 858 859 return(ret); 860 } 861 862 872 873 public static boolean stringContainsTargetTable(String str) { 874 875 if (str == null) 876 return false; 879 880 if (tableList == null) 881 return true; 883 884 int strLen = str.length(); 885 for (int i = 0; i < tableList.size(); i++) { 886 887 String tableName = (String )tableList.get(i); 888 tableName = expandDoubleQuotes(stripQuotes(tableName)); 889 int nameLen = tableName.length(); 890 String strCopy; 891 if (tableName.equals(tableName.toUpperCase( 892 java.util.Locale.ENGLISH))) 893 strCopy = str.toUpperCase(); 895 else 896 strCopy = str; 897 int pos = strCopy.indexOf(tableName); 898 while (pos != -1) { 899 900 if (!partOfWord(str, pos, nameLen, strLen)) { 903 904 if ((pos >= 1) && (strCopy.charAt(pos-1) == '"') && 907 (pos + nameLen < strCopy.length()) && 908 (strCopy.charAt(pos+nameLen) == '"')) 909 { if (str.substring(pos, 911 pos + nameLen).equals(tableName)) 912 return true; 914 } 915 else 916 return true; 918 } 919 920 pos = str.indexOf(tableName, pos + nameLen); 921 922 } 923 } 924 925 return false; 927 928 } 929 930 947 948 private static boolean partOfWord (String str, 949 int pos, int nameLen, int strLen) 950 { 951 952 boolean somethingBefore = false; 953 if (pos > 0) { 954 char c = str.charAt(pos-1); 955 somethingBefore = ((c == '_') || 956 Character.isLetterOrDigit(c)); 957 } 958 959 boolean somethingAfter = false; 960 if (pos + nameLen < strLen) { 961 char c = str.charAt(pos + nameLen); 962 somethingAfter = ((c == '_') || 963 Character.isLetterOrDigit(c)); 964 } 965 966 return (somethingBefore || somethingAfter); 967 968 } 969 970 977 978 public static String expandDoubleQuotes(String name) { 979 980 if ((name == null) || (name.indexOf("\"") < 0)) 981 return name; 983 984 char [] cA = name.toCharArray(); 985 986 char [] result = new char[2*cA.length]; 990 991 int j = 0; 992 for (int i = 0; i < cA.length; i++) { 993 994 if (cA[i] == '"') { 995 result[j++] = '"'; 996 result[j++] = '"'; 997 } 998 else 999 result[j++] = cA[i]; 1000 1001 } 1002 1003 return new String (result, 0, j); 1004 1005 } 1006 1007 1014 1015 public static String lookupSchemaId(String schemaId) { 1016 1017 return (String )(schemaMap.get(schemaId)); 1018 1019 } 1020 1021 1028 1029 public static String lookupTableId(String tableId) { 1030 1031 return (String )(tableIdToNameMap.get(tableId)); 1032 1033 } 1034 1035 1050 1051 public static void writeVerboseOutput(String key, 1052 String value) { 1053 1054 if (value == null) 1055 System.err.println(lookupMessage(key)); 1056 else 1057 System.err.println(lookupMessage(key, 1058 new String [] {value})); 1059 return; 1060 1061 } 1062 1063 1070 1071 public static String lookupMessage(String key) { 1072 1073 return lookupMessage(key, null); 1074 1075 } 1076 1077 1087 1088 public static String lookupMessage(String key, String [] vals) { 1089 1090 String msg = ""; 1091 if (vals == null) 1092 msg = langUtil.getTextMessage(key); 1093 else { 1094 switch (vals.length) { 1095 case 1: msg = langUtil.getTextMessage( 1096 key, vals[0]); 1097 break; 1098 case 2: msg = langUtil.getTextMessage( 1099 key, vals[0], vals[1]); 1100 break; 1101 default: 1102 break; 1103 } 1104 } 1105 1106 return msg; 1107 1108 } 1109 1110 1119 1120 public static String removeNewlines(String str) { 1121 1122 if (str == null) 1123 return null; 1125 1126 StringBuffer result = null; 1127 try { 1128 1129 BufferedReader strVal = new BufferedReader (new StringReader (str)); 1130 for (String txt = strVal.readLine(); txt != null; 1131 txt = strVal.readLine()) 1132 { 1133 if (result == null) 1134 result = new StringBuffer (txt); 1135 else { 1136 result.append(" "); 1137 result.append(txt); 1138 } 1139 } 1140 1141 return result.toString(); 1142 1143 } catch (Exception e) { 1144 return str; 1149 } 1150 1151 } 1152 1153} 1154 1155 | Popular Tags |