0001: /*
0002:
0003: Derby - Class org.apache.derbyTesting.functionTests.tests.tools.dblook_test
0004:
0005: Licensed to the Apache Software Foundation (ASF) under one or more
0006: contributor license agreements. See the NOTICE file distributed with
0007: this work for additional information regarding copyright ownership.
0008: The ASF licenses this file to You under the Apache License, Version 2.0
0009: (the "License"); you may not use this file except in compliance with
0010: the License. You may obtain a copy of the License at
0011:
0012: http://www.apache.org/licenses/LICENSE-2.0
0013:
0014: Unless required by applicable law or agreed to in writing, software
0015: distributed under the License is distributed on an "AS IS" BASIS,
0016: WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
0017: See the License for the specific language governing permissions and
0018: limitations under the License.
0019:
0020: */
0021:
0022: package org.apache.derbyTesting.functionTests.tests.tools;
0023:
0024: import java.sql.DriverManager;
0025: import java.sql.ResultSet;
0026: import java.sql.Connection;
0027: import java.sql.Statement;
0028: import java.sql.PreparedStatement;
0029: import java.sql.ResultSetMetaData;
0030: import java.sql.SQLException;
0031: import java.sql.SQLWarning;
0032: import java.sql.Timestamp;
0033:
0034: import java.io.PrintWriter;
0035: import java.io.FileOutputStream;
0036: import java.io.FileNotFoundException;
0037: import java.io.BufferedReader;
0038: import java.io.FileReader;
0039: import java.io.File;
0040:
0041: import org.apache.derby.tools.dblook;
0042: import org.apache.derby.tools.ij;
0043: import org.apache.derby.catalog.DependableFinder;
0044: import org.apache.derbyTesting.functionTests.util.TestUtil;
0045:
0046: import java.util.HashMap;
0047: import java.util.TreeMap;
0048: import java.util.Set;
0049: import java.util.Iterator;
0050: import java.util.ArrayList;
0051: import java.util.StringTokenizer;
0052:
0053: public class dblook_test {
0054:
0055: private static final int SERVER_PORT = 1527;
0056: private static final int FRONT = -1;
0057: private static final int REAR = 1;
0058:
0059: protected static final String dbCreationScript_1 = "dblook_makeDB.sql";
0060: protected static final String dbCreationScript_2 = "dblook_makeDB_2.sql";
0061: private static final char TEST_DELIMITER = '#';
0062:
0063: protected static String testDirectory = "dblook_test";
0064: protected static final String testDBName = "wombat";
0065: protected static String separator;
0066:
0067: private static String dbPath;
0068: private static int duplicateCounter = 0;
0069: private static int sysNameCount = 0;
0070: private static String jdbcProtocol;
0071:
0072: /* **********************************************
0073: * main:
0074: ****/
0075:
0076: public static void main(String[] args) {
0077:
0078: separator = System.getProperty("file.separator");
0079: new dblook_test().doTest();
0080: System.out.println("\n[ Done. ]\n");
0081:
0082: }
0083:
0084: /* **********************************************
0085: * doTest
0086: * Run a full test of the dblook utility.
0087: ****/
0088:
0089: protected void doTest() {
0090:
0091: try {
0092:
0093: // Test full dblook functionality.
0094: System.out
0095: .println("\n-= Start dblook Functional Tests. =-");
0096: createTestDatabase(dbCreationScript_1);
0097: runDBLook(testDBName);
0098:
0099: // Test dblook messages.
0100: System.out.println("\n-= Start dblook Message Tests =-");
0101: createTestDatabase(dbCreationScript_2);
0102: runMessageCheckTest(testDBName);
0103:
0104: } catch (SQLException se) {
0105:
0106: System.out.println("FAILED: to complete the test:");
0107: se.printStackTrace(System.out);
0108: for (se = se.getNextException(); se != null; se = se
0109: .getNextException()) {
0110: se.printStackTrace(System.out);
0111: }
0112:
0113: } catch (Exception e) {
0114:
0115: System.out.println("FAILED: to complete the test:");
0116: e.printStackTrace(System.out);
0117:
0118: }
0119:
0120: }
0121:
0122: /* **********************************************
0123: * createTestDatabase:
0124: * Using the creation script created as part of
0125: * the test package, create the database that
0126: * will be used as the basis for all dblook
0127: * tests.
0128: * @param scriptName The name of the sql script
0129: * to use for creating the test database.
0130: * @return The test database has been created
0131: * in the current test directory, which is
0132: * "./dblook/" (as created by the harness).
0133: ****/
0134:
0135: protected void createTestDatabase(String scriptName)
0136: throws Exception {
0137:
0138: // Delete existing database, if it exists.
0139: try {
0140: deleteDB(testDBName);
0141: } catch (Exception e) {
0142: System.out.println("** Warning: failed to delete "
0143: + "old test db before creating a new one...");
0144: }
0145:
0146: Class.forName("org.apache.derby.jdbc.EmbeddedDriver")
0147: .newInstance();
0148: jdbcProtocol = "jdbc:derby:";
0149: createDBFromDDL(testDBName, scriptName);
0150:
0151: // Figure out where our database directory is (abs path).
0152: String systemhome = System.getProperty("derby.system.home");
0153: dbPath = systemhome + File.separatorChar;
0154: return;
0155:
0156: }
0157:
0158: /* **********************************************
0159: * runDBLook:
0160: * Runs a series of tests using dblook on
0161: * the received database.
0162: * @param dbName The name of the database on which to
0163: * run the tests.
0164: * @return A series of tests intended to verify
0165: * the full functionality of the dblook utility
0166: * has been run.
0167: ****/
0168:
0169: private void runDBLook(String dbName) throws Exception {
0170:
0171: // Close the error stream, so that messages
0172: // printed to System.err aren't intermixed
0173: // with our output (otherwise, the order
0174: // of the System.out vs System.err is
0175: // arbitrary (because of the way the harness
0176: // works), and so we will get diffs with
0177: // the master.
0178: System.err.close();
0179:
0180: // First, we dump all system catalogs for
0181: // the original source database to file.
0182: dumpSysCatalogs(dbName);
0183:
0184: // Then, we run dblook on the source database
0185: // with no limitations (i.e. we generate the
0186: // DDL for the FULL database).
0187: lookOne(dbName);
0188: dumpFileToSysOut("dblook.log");
0189:
0190: // Now, create new db from the DDL that
0191: // was generated by dblook.
0192: String newDBName = dbName + "_new";
0193: createDBFromDDL(newDBName, dbName + ".sql");
0194: deleteFile(new File(dbName + ".sql"));
0195:
0196: // Dump all system catalogs for the database
0197: // that was created from the DDL generated
0198: // by dblook.
0199: dumpSysCatalogs(newDBName);
0200:
0201: // Delete the new database.
0202: deleteDB(newDBName);
0203: deleteFile(new File(newDBName + ".sql"));
0204:
0205: // Run dblook on the source database
0206: // with various parameter configurations,
0207: // to make sure they are all working as
0208: // planned.
0209: runAllTests(dbName, newDBName);
0210:
0211: }
0212:
0213: /* **********************************************
0214: * runAllTests:
0215: * Makes the call to execute each of the desired
0216: * tests.
0217: * @param dbName The name of the database on which to
0218: * run the tests.
0219: * @param newDBName The name of the database to be
0220: * created from the DDL that is generated (by
0221: * dblook) for the source database.
0222: ****/
0223:
0224: protected void runAllTests(String dbName, String newDBName)
0225: throws Exception {
0226:
0227: runTest(2, dbName, newDBName);
0228:
0229: // Test 3 is run as part of derbynet suite;
0230: // see derbynet/dblook_test_net.java.
0231:
0232: runTest(4, dbName, newDBName);
0233: runTest(5, dbName, newDBName);
0234: runTest(7, dbName, newDBName);
0235: runTest(6, dbName, newDBName);
0236: return;
0237:
0238: }
0239:
0240: /* **********************************************
0241: * runTest:
0242: * Runs dblook on the source database with a
0243: * specific set of parameters, then uses the
0244: * resultant DDL to create a new database, and
0245: * dumps the system catalogs for that database
0246: * to file. Finally, the new database is deleted
0247: * in preparation for subsequent calls to this
0248: * method.
0249: * @param whichTest An indication of which test to run;
0250: * each test number has a different set of
0251: * parameters.
0252: * @param dbName The name of the source database.
0253: * @param newDBName The name of the database to be
0254: * created from the DDL that is generated (by
0255: * dblook) for the source database.
0256: * @return dblook has been executed using the
0257: * parameters associated with the given test,
0258: * and that DDL has been written to a ".sql"
0259: * file named after the source database;
0260: * a new database has been created from the
0261: * ".sql" generated by dblook; the system
0262: * catalogs for that new database have been
0263: * dumped to output; and the new database has
0264: * been deleted.
0265: ****/
0266:
0267: protected void runTest(int whichTest, String dbName,
0268: String newDBName) {
0269:
0270: try {
0271:
0272: switch (whichTest) {
0273: case 2:
0274: lookTwo(dbName);
0275: break;
0276: case 3:
0277: lookThree(dbName);
0278: break;
0279: case 4:
0280: lookFour(dbName);
0281: break;
0282: case 5:
0283: lookFive(dbName);
0284: break;
0285: case 6:
0286: lookSix(dbName);
0287: break;
0288: case 7:
0289: lookSeven(dbName);
0290: break;
0291: default:
0292: break;
0293: }
0294:
0295: dumpFileToSysOut("dblook.log");
0296: createDBFromDDL(newDBName, dbName + ".sql");
0297: dumpSysCatalogs(newDBName);
0298: deleteDB(newDBName);
0299: deleteFile(new File(dbName + ".sql"));
0300:
0301: } catch (SQLException e) {
0302:
0303: System.out.println("FAILED: Test # : " + whichTest);
0304: e.printStackTrace(System.out);
0305: for (e = e.getNextException(); e != null; e = e
0306: .getNextException()) {
0307: e.printStackTrace(System.out);
0308: }
0309:
0310: } catch (Exception e) {
0311:
0312: System.out.println("FAILED: Test # : " + whichTest);
0313: e.printStackTrace(System.out);
0314:
0315: }
0316:
0317: return;
0318:
0319: }
0320:
0321: /* **********************************************
0322: * lookOne:
0323: * Use dblook to generate FULL DDL for a given
0324: * database.
0325: * @param dbName The name of the source database (i.e.
0326: * the database for which the DDL is generated).
0327: * @return The full DDL for the source database
0328: * has been generated and written to a file
0329: * called <dbName + ".sql">.
0330: ****/
0331:
0332: private void lookOne(String dbName) throws Exception {
0333:
0334: printAsHeader("\nDumping full schema for '" + dbName
0335: + "'\nto file '" + dbName + ".sql':\n");
0336:
0337: String[] args = new String[] { "-o", dbName + ".sql", "-td", "" };
0338:
0339: go(dbName, args);
0340: return;
0341:
0342: }
0343:
0344: /* **********************************************
0345: * lookTwo:
0346: * Use dblook to generate DDL for all objects
0347: * in the source database with schema 'BAR',
0348: * excluding views:
0349: * -z bar -noview
0350: * @param dbName The name of the source database (i.e.
0351: * the database for which the DDL is generated).
0352: * @return The appropriate DDL has been generated
0353: * and written to a file called <dbName + ".sql">.
0354: ****/
0355:
0356: private void lookTwo(String dbName) throws Exception {
0357:
0358: printAsHeader("\nDumping DDL for all objects "
0359: + "with schema\n'BAR', excluding views:\n");
0360:
0361: String[] args = new String[] { "-o", dbName + ".sql", "-td",
0362: "", "-z", "bar", "-noview" };
0363:
0364: go(dbName, args);
0365: return;
0366:
0367: }
0368:
0369: /* **********************************************
0370: * lookThree:
0371: * Use dblook to generate DDL for all objects
0372: * in the source database, using Network
0373: * Server.
0374: * @param dbName The name of the source database (i.e.
0375: * the database for which the DDL is generated).
0376: * @return The appropriate DDL has been generated
0377: * and written to a file called <dbName + ".sql">.
0378: ****/
0379:
0380: private void lookThree(String dbName) throws Exception {
0381:
0382: printAsHeader("\nDumping DDL for all objects, "
0383: + "using\nNetwork Server:\n");
0384: String hostName = TestUtil.getHostName();
0385: jdbcProtocol = TestUtil.getJdbcUrlPrefix(hostName, SERVER_PORT);
0386:
0387: String sourceDBUrl;
0388: if (TestUtil.isJCCFramework())
0389: sourceDBUrl = jdbcProtocol + "\"" + dbPath + separator
0390: + dbName + "\":user=someusr;password=somepwd;";
0391: else
0392: sourceDBUrl = jdbcProtocol + dbPath + separator + dbName
0393: + ";user=someusr;password=somepwd";
0394:
0395: // Make sure we're not connected to the database
0396: // (we connected to it in embedded mode when we
0397: // created it, so we have to shut it down).
0398: try {
0399: DriverManager.getConnection("jdbc:derby:" + dbName
0400: + ";shutdown=true");
0401: } catch (SQLException e) {
0402: }
0403:
0404: // Run the test.
0405: try {
0406:
0407: new dblook(new String[] { "-d", sourceDBUrl, "-o",
0408: dbName + ".sql", "-td", "" });
0409:
0410: } catch (Exception e) {
0411: System.out.println("FAILED: ");
0412: e.printStackTrace(System.out);
0413: }
0414:
0415: return;
0416:
0417: }
0418:
0419: /* **********************************************
0420: * lookFour:
0421: * Use dblook to generate DDL for all objects
0422: * in the source database with schema 'BAR'
0423: * that are related to tables 'T3', 'tWithKeys',
0424: * and 'MULTI WORD NAME'.
0425: * -z bar -t t3 "\"tWithKeys\"" "Multi word name"
0426: * @param dbName The name of the source database (i.e.
0427: * the database for which the DDL is generated).
0428: * @return The appropriate DDL has been generated
0429: * and written to a file called <dbName + ".sql">.
0430: ****/
0431:
0432: private void lookFour(String dbName) throws Exception {
0433:
0434: printAsHeader("\nDumping DDL for all objects "
0435: + "with schema 'BAR'\nthat are related to tables "
0436: + "'T3', 'tWithKeys',\nand 'MULTI WORD NAME':\n");
0437:
0438: String[] args = new String[] { "-o", dbName + ".sql", "-td",
0439: "", "-z", "BAR", "-t", "t3", "\"tWithKeys\"",
0440: "Multi word name" };
0441:
0442: go(dbName, args);
0443: return;
0444:
0445: }
0446:
0447: /* **********************************************
0448: * lookFive:
0449: * Use dblook to generate DDL for all objects
0450: * in the source database (with any schema)
0451: * that are related to table 'T1' and 'TWITHKEYS'
0452: * (with no matches existing for the latter).
0453: * -t t1 "tWithKeys"
0454: * @param dbName The name of the source database (i.e.
0455: * the database for which the DDL is generated).
0456: * @return The appropriate DDL has been generated
0457: * and written to a file called <dbName + ".sql">.
0458: ****/
0459:
0460: private void lookFive(String dbName) throws Exception {
0461:
0462: printAsHeader("\nDumping DDL for all objects "
0463: + "related to 'T1'\nand 'TWITHKEYS':\n");
0464:
0465: String[] args = new String[] { "-o", dbName + ".sql", "-td",
0466: "", "-t", "t1", "tWithKeys" };
0467:
0468: go(dbName, args);
0469: return;
0470:
0471: }
0472:
0473: /* **********************************************
0474: * lookSix:
0475: * Call dblook with an invalid url, to make
0476: * sure that errors are printed to log.
0477: * -d <dbName> // missing protocol.
0478: * @param dbName The name of the source database (i.e.
0479: * the database for which the DDL is generated).
0480: * @return The appropriate DDL has been generated
0481: * and written to a file called <dbName + ".sql">.
0482: ****/
0483:
0484: private void lookSix(String dbName) throws Exception {
0485:
0486: printAsHeader("\nDumping DDL w/ invalid url, and "
0487: + "writing\nerror to the log:\n");
0488:
0489: // Url is intentionally incorrect; it will cause an error.
0490: new dblook(new String[] { "-o", dbName + ".sql", "-d", dbName });
0491:
0492: }
0493:
0494: /* **********************************************
0495: * lookSeven:
0496: * Use dblook to generate DDL for all objects
0497: * in the source database with schema '"Quoted"Schema"'.
0498: * -z \"\"Quoted\"Schema\"\"
0499: * @param dbName The name of the source database (i.e.
0500: * the database for which the DDL is generated).
0501: * @return The appropriate DDL has been generated
0502: * and written to a file called <dbName + ".sql">.
0503: ****/
0504:
0505: private void lookSeven(String dbName) throws Exception {
0506:
0507: printAsHeader("\nDumping DDL for all objects "
0508: + "with schema\n'\"Quoted\"Schema\"':\n");
0509:
0510: String[] args = new String[] { "-o", dbName + ".sql", "-td",
0511: "", "-z", "\"\"Quoted\"Schema\"\"" };
0512:
0513: go(dbName, args);
0514: return;
0515:
0516: }
0517:
0518: /* **********************************************
0519: * go:
0520: * Makes the call to execute the dblook command
0521: * using the received arguments.
0522: * @param dbName The name of the source database (i.e.
0523: * the database for which the DDL is generated).
0524: * @args The list of arguments with which to execute
0525: * the dblook command.
0526: ****/
0527:
0528: private void go(String dbName, String[] args) {
0529:
0530: jdbcProtocol = "jdbc:derby:";
0531: String sourceDBUrl = jdbcProtocol + dbPath + separator + dbName;
0532:
0533: String[] fullArgs = new String[args.length + 2];
0534: fullArgs[0] = "-d";
0535: fullArgs[1] = sourceDBUrl;
0536: for (int i = 2; i < fullArgs.length; i++)
0537: fullArgs[i] = args[i - 2];
0538:
0539: try {
0540: new dblook(fullArgs);
0541: } catch (Exception e) {
0542: System.out.println("FAILED: to run dblook: ");
0543: e.printStackTrace(System.out);
0544: }
0545:
0546: }
0547:
0548: /* **********************************************
0549: * runMessageCheckTest
0550: * Run dblook and verify that all of the dblook
0551: * messages are correctly displayed.
0552: * @param dbName The name of the source database (i.e.
0553: * the database for which the DDL is generated).
0554: * @return The DDL for a simple database, plus all
0555: * dblook messages, have been generated and written
0556: * to System.out.
0557: ****/
0558: private void runMessageCheckTest(String dbName) throws Exception {
0559:
0560: // #1: First, run DB look standard to check for
0561: // all of the "header" messages that are printed
0562: // out along with DDL.
0563: System.out.println("\n************\n" + "Msg Test 1\n"
0564: + "************\n");
0565: lookOne(dbName);
0566: dumpFileToSysOut(dbName + ".sql");
0567: dumpFileToSysOut("dblook.log");
0568:
0569: // Now, we have to run some additional dblook commands
0570: // to get the "non-standard" messages.
0571:
0572: // #2: Specify a target table and target schema, to
0573: // make sure they are echoed correctly. Also, specify
0574: // an output file to make sure the file creation header
0575: // is printed in the file.
0576: System.out.println("\n************\n" + "Msg Test 2\n"
0577: + "************\n");
0578: go(dbName, new String[] { "-t", "t1", "-z", "bar", "-o",
0579: dbName + ".sql" });
0580: dumpFileToSysOut(dbName + ".sql");
0581: dumpFileToSysOut("dblook.log");
0582:
0583: // #3: Run without specifying a database, to make
0584: // sure the usage message is printed to System.out
0585: System.out.println("\n************\n" + "Msg Test 3\n"
0586: + "************\n");
0587: try {
0588: new dblook(new String[] { "-verbose" });
0589: } catch (Exception e) {
0590: System.out.println("FAILED: to run dblook: ");
0591: e.printStackTrace(System.out);
0592: }
0593:
0594: // #4: Just to confirm, try once with a statement
0595: // delimiter, to make sure it's actually working
0596: // correctly (this isn't a "message" per se, but
0597: // still, it's worth verifying).
0598: System.out.println("\n************\n" + "Msg Test 4\n"
0599: + "************\n");
0600: go(dbName, new String[] { "-td", " " + TEST_DELIMITER });
0601:
0602: // #5: Intentionally create an error while loading
0603: // a jar file, to make sure the resultant message is
0604: // printed correctly.
0605: System.out.println("\n************\n" + "Msg Test 5\n"
0606: + "************\n");
0607:
0608: // We'll cause the error by going in and deleting
0609: // the jar file from the test database. First,
0610: // get the jar path.
0611: String jarPath = (new File(dbPath + separator + dbName))
0612: .getAbsolutePath();
0613:
0614: // Have to shut db down before we can mess with it.
0615: try {
0616: Connection conn = DriverManager.getConnection("jdbc:derby:"
0617: + jarPath + ";shutdown=true");
0618: conn.close();
0619: } catch (SQLException se) {
0620: // shutdown exception.
0621: }
0622:
0623: jarPath = jarPath + separator + "jar";
0624: deleteFile(new File(jarPath));
0625:
0626: // Now that we've deleted the jar file, run dblook
0627: // and check the error.
0628: go(dbName, new String[] { "-verbose", "-o", dbName + ".sql" });
0629: dumpFileToSysOut("dblook.log");
0630:
0631: // Clean up.
0632: try {
0633: deleteFile(new File(dbName + ".sql"));
0634: } catch (Exception e) {
0635: // not too big of a deal if we fail; just ignore...
0636: }
0637:
0638: }
0639:
0640: /* **********************************************
0641: * dumpSysCatalogs:
0642: * Takes a database name and dumps ALL of the
0643: * system catalogs for that database, with the
0644: * exception of SYSSTATISTICS. This allows us
0645: * to look at the full contents of a database's
0646: * schema (without using dblook, of course)
0647: * so that we can see if the databases created
0648: * from the DDL generated by dblook have been
0649: * built correctly--if they have all of the
0650: * correct system catalog information, then
0651: * the databases themselves must be correct.
0652: * @param dbName The name of the database for which
0653: * we are dumping the system catalogs.
0654: * @return All of the system catalogs for
0655: * the received database have been dumped
0656: * to output.
0657: ****/
0658:
0659: private void dumpSysCatalogs(String dbName) throws Exception {
0660:
0661: System.out.println("\nDumping system tables for '" + dbName
0662: + "'\n");
0663:
0664: writeOut("\n----------------=================---------------");
0665: writeOut("System Tables for: " + dbName);
0666: writeOut("----------------=================---------------\n");
0667:
0668: // Connect to the database.
0669: Connection conn = DriverManager.getConnection("jdbc:derby:"
0670: + dbName);
0671: conn.setAutoCommit(false);
0672: Statement stmt = conn.createStatement();
0673:
0674: // Load any id-to-name mappings that will be useful
0675: // when dumping the catalogs.
0676: HashMap idToNameMap = loadIdMappings(stmt, conn);
0677:
0678: // Go through and dump all system catalog information,
0679: // filtering out database-dependent id's so that they
0680: // won't cause diffs.
0681:
0682: writeOut("\n========== SYSALIASES ==========\n");
0683: ResultSet rs = stmt
0684: .executeQuery("select schemaid, sys.sysaliases.* from sys.sysaliases");
0685: dumpResultSet(rs, idToNameMap, null);
0686:
0687: writeOut("\n========== SYSCHECKS ==========\n");
0688: rs = stmt.executeQuery("select c.schemaid, ck.* from "
0689: + "sys.syschecks ck, sys.sysconstraints c where "
0690: + "ck.constraintid = c.constraintid");
0691: dumpResultSet(rs, idToNameMap, null);
0692:
0693: writeOut("\n========== SYSCOLUMNS ==========\n");
0694: writeOut("--- Columns for Tables ---");
0695: rs = stmt
0696: .executeQuery("select t.schemaid, c.* from "
0697: + "sys.syscolumns c, sys.systables t where c.referenceid "
0698: + "= t.tableid");
0699: dumpResultSet(rs, idToNameMap, null);
0700: writeOut("\n--- Columns for Statements ---");
0701: rs = stmt
0702: .executeQuery("select s.schemaid, c.* from "
0703: + "sys.syscolumns c, sys.sysstatements s where c.referenceid "
0704: + "= s.stmtid");
0705: dumpResultSet(rs, idToNameMap, null);
0706:
0707: writeOut("\n========== SYSCONGLOMERATES ==========\n");
0708: rs = stmt
0709: .executeQuery("select schemaid, sys.sysconglomerates.* "
0710: + "from sys.sysconglomerates");
0711: dumpResultSet(rs, idToNameMap, null);
0712:
0713: writeOut("\n========== SYSCONSTRAINTS ==========\n");
0714: rs = stmt.executeQuery("select schemaid, sys.sysconstraints.* "
0715: + "from sys.sysconstraints");
0716: dumpResultSet(rs, idToNameMap, null);
0717:
0718: writeOut("\n========== SYSDEPENDS ==========\n");
0719: rs = stmt
0720: .executeQuery("select dependentid, sys.sysdepends.* from sys.sysdepends");
0721: dumpResultSet(rs, idToNameMap, conn);
0722:
0723: writeOut("\n========== SYSFILES ==========\n");
0724: rs = stmt
0725: .executeQuery("select schemaid, sys.sysfiles.* from sys.sysfiles");
0726: dumpResultSet(rs, idToNameMap, null);
0727:
0728: writeOut("\n========== SYSFOREIGNKEYS ==========\n");
0729: rs = stmt.executeQuery("select c.schemaid, fk.* from "
0730: + "sys.sysforeignkeys fk, sys.sysconstraints c where "
0731: + "fk.constraintid = c.constraintid");
0732: dumpResultSet(rs, idToNameMap, null);
0733:
0734: writeOut("\n========== SYSKEYS ==========\n");
0735: rs = stmt.executeQuery("select c.schemaid, k.* from "
0736: + "sys.syskeys k, sys.sysconstraints c where "
0737: + "k.constraintid = c.constraintid");
0738: dumpResultSet(rs, idToNameMap, null);
0739:
0740: writeOut("\n========== SYSSCHEMAS ==========\n");
0741: rs = stmt
0742: .executeQuery("select schemaid, sys.sysschemas.* from sys.sysschemas");
0743: dumpResultSet(rs, idToNameMap, null);
0744:
0745: writeOut("\n========== SYSSTATEMENTS ==========\n");
0746: rs = stmt
0747: .executeQuery("select schemaid, sys.sysstatements.* from sys.sysstatements");
0748: dumpResultSet(rs, idToNameMap, null);
0749:
0750: writeOut("\n========== SYSTABLES ==========\n");
0751: rs = stmt
0752: .executeQuery("select schemaid, sys.systables.* from sys.systables");
0753: dumpResultSet(rs, idToNameMap, null);
0754:
0755: writeOut("\n========== SYSTRIGGERS ==========\n");
0756: rs = stmt
0757: .executeQuery("select schemaid, sys.systriggers.* from sys.systriggers");
0758: dumpResultSet(rs, idToNameMap, null);
0759:
0760: writeOut("\n========== SYSVIEWS ==========\n");
0761: rs = stmt
0762: .executeQuery("select compilationschemaid, sys.sysviews.* from sys.sysviews");
0763: dumpResultSet(rs, idToNameMap, null);
0764:
0765: stmt.close();
0766: rs.close();
0767: conn.commit();
0768: conn.close();
0769: return;
0770:
0771: }
0772:
0773: /* **********************************************
0774: * isIgnorableSchema:
0775: * Returns true if the the schema is a "system" schema, vs. a user
0776: * schema.
0777: * @param schemaName name of schema to check.
0778: ****/
0779: private boolean isIgnorableSchema(String schemaName) {
0780:
0781: boolean ret = false;
0782:
0783: for (int i = ignorableSchemaNames.length - 1; i >= 0;) {
0784: if ((ret = ignorableSchemaNames[i--]
0785: .equalsIgnoreCase(schemaName)))
0786: break;
0787: }
0788:
0789: return (ret);
0790: }
0791:
0792: private static final String[] ignorableSchemaNames = { "SYSIBM",
0793: "SYS", "SYSVISUAL", "SYSCAT", "SYSFUN", "SYSPROC",
0794: "SYSSTAT", "NULLID", "SYSCS_ADMIN", "SYSCS_DIAG",
0795: "SYSCS_UTIL", "SQLJ" };
0796:
0797: /* **********************************************
0798: * dumpResultSet:
0799: * Iterates through the received result set and
0800: * dumps ALL columns in ALL rows of that result
0801: * set to output. Since no order is guaranteed
0802: * in the received result set, we have to generate
0803: * unique "ids" for each row in the result, and
0804: * then use those ids to determine what order the
0805: * rows will be output. Failure to do so will
0806: * lead to diffs in the test for rows that occur
0807: * out of order. The unique id's must NOT
0808: * depend on system-generated id's, as the
0809: * latter will vary for every run of the test,
0810: * and thus will lead to different orderings
0811: * every time (which we don't want).
0812: *
0813: * @param rs The result set that is being dumped.
0814: * @param idToNameMap Mapping of various ids to
0815: * object names; used in forming unique ids.
0816: * @param conn Connection from which the result set
0817: * originated.
0818: ****/
0819:
0820: private void dumpResultSet(ResultSet rs, HashMap idToNameMap,
0821: Connection conn) throws Exception {
0822:
0823: // We need to form unique names for the rows of the
0824: // result set so that we can preserve the order of
0825: // the output and avoid diffs with a master. This is
0826: // because a "select *" doesn't order rows--and even
0827: // though the schema for two databases might be the
0828: // same (i.e. the system tables contain all of the same
0829: // information) there's nothing to say the various rows in
0830: // the respective system tables will be the same (they
0831: // usually are NOT). While system id's automatically
0832: // give us uniqueness, we can NOT order on them because
0833: // they vary from database to database; so, we need
0834: // to use something constant across the databases,
0835: // which is why we use object names.
0836: StringBuffer uniqueName = new StringBuffer();
0837:
0838: TreeMap orderedRows = new TreeMap();
0839: ArrayList rowValues = new ArrayList();
0840: ArrayList duplicateRowIds = new ArrayList();
0841:
0842: ResultSetMetaData rsmd = rs.getMetaData();
0843: int cols = rsmd.getColumnCount();
0844: while (rs.next()) {
0845:
0846: for (int i = 1; i <= cols; i++) {
0847:
0848: String colName = rsmd.getColumnName(i);
0849: String value = rs.getString(i);
0850: String mappedName = (String) idToNameMap.get(value);
0851:
0852: if ((colName.indexOf("SCHEMAID") != -1)
0853: && (mappedName != null)
0854: && ((mappedName.indexOf("SYS") != -1) || (isIgnorableSchema(mappedName)))) {
0855: // then this row of the result set is for a system
0856: // object, which will always be the same for the
0857: // source and new database, so don't bother dumping
0858: // them to the output file (makes the test less
0859: // like to require updates when changes to database
0860: // metadata for system objects are checked in).
0861: rowValues = null;
0862: break;
0863: } else if (colName.equals("JAVACLASSNAME")
0864: && (value != null)
0865: && (value.indexOf("org.apache.derby") != -1)
0866: && (value.indexOf(".util.") == -1)) {
0867: // this is a -- hack -- to see if the alias is a
0868: // a system alias, needed because aliases
0869: // (other than stored procedures) do not have
0870: // an associated schema).
0871: rowValues = null;
0872: break;
0873: }
0874:
0875: if (i == 1)
0876: // 1st column is just for figuring out whether
0877: // to dump this row; no need to actually include
0878: // it in the results.
0879: continue;
0880:
0881: String uniquePiece = dumpColumnData(colName, value,
0882: mappedName, rowValues);
0883:
0884: if (colName.equals("DEPENDENTID")) {
0885: // Special case: rows in the "DEPENDS" table
0886: // don't have unique ids or names; we have to
0887: // build one by extracting information indirectly.
0888: String hiddenInfo = getDependsData(rs, conn,
0889: idToNameMap);
0890: if (hiddenInfo.indexOf("SYS_OBJECT") != -1) {
0891: // this info is for a system object, so
0892: // ignore it.
0893: rowValues = null;
0894: break;
0895: }
0896: uniqueName.append(hiddenInfo);
0897: // Include the hidden data as part of the
0898: // output.
0899: rowValues.add(hiddenInfo);
0900: }
0901:
0902: if (uniquePiece != null)
0903: uniqueName.append(uniquePiece);
0904:
0905: if (colName.equals("STMTNAME")
0906: && (value.indexOf("TRIGGERACTN") != -1))
0907: // Special case: can't use statement name, because
0908: // the entire statement may be automatically generated
0909: // in each database (to back a trigger), so the name
0910: // in which case the generated name will be different
0911: // every time; but filtering out the name means
0912: // we have no other guaranteed unique 'id' for
0913: // ordering. So, just take "text" field, and
0914: // design test db so that no two triggers have the
0915: // same text value.
0916: uniqueName.append(rs.getString(6));
0917:
0918: }
0919:
0920: if (rowValues != null) {
0921:
0922: if (duplicateRowIds.contains(uniqueName.toString()))
0923: // then we've already encountered this row id before;
0924: // to preserve ordering, use the entire row as an
0925: // id.
0926: handleDuplicateRow(rowValues, null, orderedRows);
0927: else {
0928: ArrayList oldRow = (ArrayList) (orderedRows.put(
0929: uniqueName.toString(), rowValues));
0930: if (oldRow != null) {
0931: // Duplicate row id.
0932: duplicateRowIds.add(uniqueName.toString());
0933: // Delete the row that has the duplicate row id.
0934: orderedRows.remove(uniqueName.toString());
0935: handleDuplicateRow(rowValues, oldRow,
0936: orderedRows);
0937: }
0938: }
0939: }
0940:
0941: uniqueName = new StringBuffer();
0942: rowValues = new ArrayList();
0943:
0944: }
0945:
0946: // Now, print out all of the data in this result set
0947: // using the order of the unique names that we created.
0948: Set objectNames = orderedRows.keySet();
0949: for (Iterator itr = objectNames.iterator(); itr.hasNext();) {
0950:
0951: String row = (String) itr.next();
0952: ArrayList colData = (ArrayList) orderedRows.get(row);
0953: for (int i = 0; i < colData.size(); i++)
0954: writeOut((String) colData.get(i));
0955: writeOut("----");
0956:
0957: }
0958:
0959: orderedRows = null;
0960: rs.close();
0961:
0962: }
0963:
0964: /* **********************************************
0965: * dumpColumnData:
0966: * Stores the value for a specific column of
0967: * some result set. If the value needs to
0968: * be filtered (to remove system-generated ids
0969: * that would otherwise cause diffs with the
0970: * master), that filtering is done here.
0971: * @param colName Name of the column whose value we're
0972: * writing.
0973: * @param value Value that we're writing.
0974: * @param mappedName: Name corresponding to the value,
0975: * for cases where the value is actually an
0976: * object id (then we want to write the name
0977: * instead).
0978: * rowValues a list of column values for the
0979: * current row of the result set.
0980: * @return The (possibly filtered) value of the
0981: * received column has been added to the
0982: * "rowVals" array list, and the corresponding
0983: * piece of the row's unique name has been
0984: * returned, if one exists.
0985: ****/
0986:
0987: private String dumpColumnData(String colName, String value,
0988: String mappedName, ArrayList rowVals) {
0989:
0990: if (mappedName == null) {
0991: // probably not an id.
0992: if (colName.equals("CONGLOMERATENUMBER")
0993: || colName.equals("GENERATIONID"))
0994: // special case: these numbers aren't ids per
0995: // se, but they are still generated by the system,
0996: // and will cause diffs with the master; so, ignore
0997: // them.
0998: rowVals.add("<systemnumber>");
0999: else if (colName.equals("AUTOINCREMENTVALUE"))
1000: // special case: new database won't have any data,
1001: // old will, so unless we filter this out, we'll
1002: // get a diff.
1003: rowVals.add("<autoincval>");
1004: else if (colName.equals("VALID"))
1005: // special case: ignore whether or not stored
1006: // statements are valid (have been compiled)
1007: // since it depends on history of database,
1008: // which we can't duplicate.
1009: rowVals.add("<validityflag>");
1010: else if (value != null) {
1011: if (looksLikeSysGenName(value)) {
1012: if (columnHoldsObjectName(colName))
1013: rowVals.add("<systemname>");
1014: else {
1015: // looks like a sys gen name, but's actually a VALUE.
1016: rowVals.add(value);
1017: return value;
1018: }
1019: } else if (looksLikeSysGenId(value))
1020: rowVals.add("<systemid>");
1021: else {
1022: rowVals.add(value);
1023: if (columnHoldsObjectName(colName))
1024: // if it's a name, we need it as part of
1025: // our unique id.
1026: return value;
1027: }
1028: } else
1029: // null value.
1030: rowVals.add(value);
1031: } else {
1032: // it's an id, so write the corresponding name.
1033: if (!isSystemGenerated(mappedName)) {
1034: // Not an id-as-name, so use it as part of our unique id.
1035: rowVals.add(mappedName);
1036: return mappedName;
1037: } else
1038: rowVals.add("<systemname>");
1039: }
1040:
1041: // If we get here, we do NOT want the received value
1042: // to be treated as part of this row's unique name.
1043: return null;
1044:
1045: }
1046:
1047: /* **********************************************
1048: * handleDuplicateRow:
1049: * If we get here, then despite our efforts (while
1050: * dumping the system catalogs for a database), we
1051: * still have a duplicate row id. So, as a last
1052: * resort we just use the ENTIRE row as a 'row id'.
1053: * In the rare-but-possible case that the entire
1054: * row is a duplicate (as can happen with the
1055: * SYSDEPENDS table), then we tag a simple number
1056: * onto the latest row's id, so that the row will
1057: * still show up multiple times--and since the rows
1058: * are identical, it doesn't matter which comes
1059: * 'first'.
1060: * @param newRow The most recently-fetched row from
1061: * the database system catalogs.
1062: * @param oldRow The row that was replaced when the
1063: * newRow was inserted (because they had the
1064: * same row id), or "null" if we were already
1065: * here once for this row id, and so just want
1066: * insert a new row.
1067: * @param orderedRows The ordered set of rows, into
1068: * which oldRow and newRow need to be inserted.
1069: * @return oldRow and newRow have been inserted
1070: * into orderedRows, and each has a (truly)
1071: * unique id with it.
1072: ****/
1073:
1074: private void handleDuplicateRow(ArrayList newRow, ArrayList oldRow,
1075: TreeMap orderedRows) {
1076:
1077: // Add the received rows (old and new) with
1078: // unique row ids.
1079:
1080: StringBuffer newRowId = new StringBuffer();
1081: for (int i = 0; i < newRow.size(); i++)
1082: newRowId.append((String) newRow.get(i));
1083:
1084: Object obj = (ArrayList) (orderedRows.put(newRowId.toString(),
1085: newRow));
1086: if (obj != null)
1087: // entire row is a duplicate.
1088: orderedRows.put(newRowId.toString() + duplicateCounter++,
1089: newRow);
1090:
1091: if (oldRow != null) {
1092:
1093: StringBuffer oldRowId = new StringBuffer();
1094: for (int i = 0; i < oldRow.size(); i++)
1095: oldRowId.append((String) oldRow.get(i));
1096:
1097: obj = (ArrayList) (orderedRows.put(oldRowId.toString(),
1098: oldRow));
1099: if (obj != null)
1100: // entire row is a duplicate.
1101: orderedRows.put(oldRowId.toString()
1102: + duplicateCounter++, oldRow);
1103: }
1104:
1105: return;
1106:
1107: }
1108:
1109: /* **********************************************
1110: * createDBFromDDL:
1111: * Read from the given script and use it to create
1112: * a new database of the given name.
1113: * @param newDBName Name of the database to be created.
1114: * @param scriptName Name of the script containing the
1115: * DDL from which the new database will be created.
1116: * @return New database has been created from
1117: * the script; any commands in the script that
1118: * failed to execute have been echoed to output.
1119: ****/
1120:
1121: private void createDBFromDDL(String newDBName, String scriptName)
1122: throws Exception {
1123:
1124: System.out.println("\n\nCreating database '" + newDBName
1125: + "' from ddl script '" + scriptName + "'");
1126:
1127: Connection conn = DriverManager.getConnection("jdbc:derby:"
1128: + newDBName + ";create=true");
1129:
1130: Statement stmt = conn.createStatement();
1131: BufferedReader ddlScript = new BufferedReader(new FileReader(
1132: scriptName));
1133:
1134: for (String sqlCmd = ddlScript.readLine(); sqlCmd != null; sqlCmd = ddlScript
1135: .readLine()) {
1136:
1137: if (sqlCmd.indexOf("--") == 0)
1138: // then this is a script comment; ignore it;
1139: continue;
1140: else if (sqlCmd.trim().length() == 0)
1141: // blank line; ignore it.
1142: continue;
1143:
1144: // Execute the command.
1145: if ((sqlCmd.charAt(sqlCmd.length() - 1) == TEST_DELIMITER)
1146: || (sqlCmd.charAt(sqlCmd.length() - 1) == ';'))
1147: // strip off the delimiter.
1148: sqlCmd = sqlCmd.substring(0, sqlCmd.length() - 1);
1149:
1150: try {
1151: stmt.execute(sqlCmd);
1152: } catch (Exception e) {
1153: System.out.println("FAILED: to execute cmd "
1154: + "from DDL script:\n" + sqlCmd + "\n");
1155: System.out.println(e.getMessage());
1156: }
1157:
1158: }
1159:
1160: // Cleanup.
1161: ddlScript.close();
1162: stmt.close();
1163: conn.close();
1164:
1165: return;
1166:
1167: }
1168:
1169: /* **********************************************
1170: * writeOut:
1171: * Write the received string to some output.
1172: * @param str String to write.
1173: ****/
1174:
1175: private static void writeOut(String str) {
1176:
1177: System.out.println(str);
1178: return;
1179:
1180: }
1181:
1182: /* **********************************************
1183: * loadIdMappings:
1184: * Load mappings of object ids to object names
1185: * for purposes of having meaningful output
1186: * and for creating unique ids on the rows of
1187: * the system catalogs.
1188: * @param stmt Statement on a connection to the
1189: * database being examined.
1190: * @param conn Connection to the database being
1191: * examined.
1192: * @return A HashMap with all relevant id-to-
1193: * name mappings has been returned.
1194: ****/
1195:
1196: private HashMap loadIdMappings(Statement stmt, Connection conn)
1197: throws Exception {
1198:
1199: HashMap idToNameMap = new HashMap();
1200:
1201: // Table ids.
1202: ResultSet rs = stmt
1203: .executeQuery("select tableid, tablename from sys.systables");
1204: while (rs.next())
1205: idToNameMap.put(rs.getString(1), rs.getString(2));
1206:
1207: // Schema ids.
1208: rs = stmt
1209: .executeQuery("select schemaid, schemaname from sys.sysschemas");
1210: while (rs.next())
1211: idToNameMap.put(rs.getString(1), rs.getString(2));
1212:
1213: // Constraint ids.
1214: rs = stmt
1215: .executeQuery("select constraintid, constraintname from "
1216: + "sys.sysconstraints");
1217: while (rs.next())
1218: idToNameMap.put(rs.getString(1), rs.getString(2));
1219:
1220: return idToNameMap;
1221:
1222: }
1223:
1224: /* **********************************************
1225: * getDependsData:
1226: * Forms a string containing detailed information
1227: * about a row in the SYSDEPENDS table, and returns
1228: * that string.
1229: * @param rs Result set with SYSDEPENDS rows; current
1230: * row is the one for which we're getting the
1231: * data.
1232: * @param conn Connection to the database being
1233: * examined.
1234: * @param idToNameMap mapping of object ids to names
1235: * for the database in question.
1236: * @return Schema, type and name of both the Provider
1237: * and the Dependent for the current row of
1238: * SYSDEPENDS have been returned as a string.
1239: ****/
1240:
1241: private String getDependsData(ResultSet rs, Connection conn,
1242: HashMap idToNameMap) throws Exception {
1243:
1244: DependableFinder dep = (DependableFinder) rs.getObject(3);
1245:
1246: DependableFinder prov = (DependableFinder) rs.getObject(5);
1247:
1248: String depType = dep.getSQLObjectType();
1249: String provType = prov.getSQLObjectType();
1250:
1251: Statement dependsStmt = conn.createStatement();
1252: StringBuffer dependsData = new StringBuffer();
1253: dependsData.append(getHiddenDependsData(depType, rs
1254: .getString(2), dependsStmt, idToNameMap));
1255: dependsData.append(" -> ");
1256: dependsData.append(getHiddenDependsData(provType, rs
1257: .getString(4), dependsStmt, idToNameMap));
1258:
1259: return dependsData.toString();
1260:
1261: }
1262:
1263: /* **********************************************
1264: * getHiddenDependsData:
1265: * Returns a string containing the schema and
1266: * name of the object having the received id.
1267: * All object ids received by this message come
1268: * from rows of the SYSDEPENDS table.
1269: * @param type Type of the object that has the received
1270: * object id.
1271: * @param id Id of the object in question.
1272: * @param stmt Statement from the database in question.
1273: * @param idToNameMap mapping of ids to names for
1274: * the database in question.
1275: * @isProvider True if we're getting data for a
1276: * Provider object; false if we're getting data for
1277: * a Dependent object.
1278: * @return Schema, type, and name for the object with
1279: * the received id have been returned as a string.
1280: ****/
1281:
1282: private String getHiddenDependsData(String type, String id,
1283: Statement pStmt, HashMap idToNameMap) throws Exception {
1284:
1285: ResultSet rs = null;
1286: if (type.equals("Constraint")) {
1287: rs = pStmt
1288: .executeQuery("select schemaid, constraintname from "
1289: + "sys.sysconstraints where "
1290: + "constraintid = '" + id + "'");
1291: } else if (type.equals("StoredPreparedStatement")) {
1292: rs = pStmt.executeQuery("select schemaid, stmtname from "
1293: + "sys.sysstatements where stmtid = '" + id + "'");
1294: } else if (type.equals("Trigger")) {
1295: rs = pStmt
1296: .executeQuery("select schemaid, triggername from "
1297: + "sys.systriggers where triggerid = '"
1298: + id + "'");
1299: } else if (type.equals("View") || type.equals("Table")
1300: || type.equals("ColumnsInTable")) {
1301: rs = pStmt.executeQuery("select schemaid, tablename from "
1302: + "sys.systables where tableid = '" + id + "'");
1303: } else if (type.equals("Conglomerate")) {
1304: rs = pStmt
1305: .executeQuery("select schemaid, conglomeratename from "
1306: + "sys.sysconglomerates where conglomerateid = '"
1307: + id + "'");
1308: } else {
1309: System.out.println("WARNING: Unexpected "
1310: + "dependent type: " + type);
1311: return "";
1312: }
1313:
1314: if (rs.next()) {
1315: String schema = (String) idToNameMap.get(rs.getString(1));
1316: if (isIgnorableSchema(schema))
1317: // system object (so we want to ignore it); indicate
1318: // this by returning the string "SYS_OBJECT".
1319: return "SYS_OBJECT";
1320: StringBuffer result = new StringBuffer();
1321: result.append("<");
1322: result.append(type);
1323: result.append(">");
1324: result.append(schema);
1325: result.append(".");
1326: if (isSystemGenerated(rs.getString(2)))
1327: result.append("<sysname>");
1328: else
1329: result.append(rs.getString(2));
1330: return result.toString();
1331: }
1332:
1333: return "";
1334:
1335: }
1336:
1337: /* **********************************************
1338: * deleteDB:
1339: * Deletes the database with the received name
1340: * from the test directory.
1341: * @param dbName Name of the database to be deleted.
1342: * @return Database has been completely deleted;
1343: * if deletion failed for any reason, a message
1344: * saying so has been printed to output.
1345: ****/
1346:
1347: private void deleteDB(String dbName) throws Exception {
1348:
1349: // Get the full path.
1350: String deletePath = (new File(dbPath + separator + dbName))
1351: .getAbsolutePath();
1352:
1353: // Have to shut it down before we can delete it.
1354: try {
1355: Connection conn = DriverManager.getConnection("jdbc:derby:"
1356: + deletePath + ";shutdown=true");
1357: conn.close();
1358: } catch (SQLException se) {
1359: // shutdown exception.
1360: }
1361:
1362: File f = new File(deletePath);
1363: if (!f.exists())
1364: // nothing to do.
1365: return;
1366:
1367: File[] files = f.listFiles();
1368: for (int i = 0; i < files.length; i++)
1369: deleteFile(files[i]);
1370:
1371: if (!f.delete()) {
1372: // still failed.
1373: System.out.println("ERROR: deleting: " + f.getName());
1374: }
1375:
1376: // And finally, delete the CSJARS directory,
1377: // if there is one.
1378: deleteFile(new File(System.getProperty("user.dir") + separator
1379: + "CSJARS"));
1380:
1381: System.out.println("Database '" + dbName + "' deleted.");
1382: return;
1383:
1384: }
1385:
1386: /* **********************************************
1387: * deleteFile:
1388: * Delete everything in a given directory, then
1389: * delete the directory itself (recursive).
1390: * @param aFile File object representing the directory
1391: * to be deleted.
1392: * @return the directory corresponding to aFile
1393: * has been deleted, as have all of its contents.
1394: ****/
1395:
1396: private void deleteFile(File aFile) throws Exception {
1397:
1398: if (!aFile.exists())
1399: // don't bother.
1400: return;
1401:
1402: if (aFile.delete())
1403: // just a file; we're done.
1404: return;
1405:
1406: // Otherwise, have to descend and delete all
1407: // files in this directory.
1408: File[] files = aFile.listFiles();
1409: if (files != null) {
1410: for (int i = 0; i < files.length; i++)
1411: deleteFile(files[i]);
1412: }
1413:
1414: // Now try to delete.
1415: if (!aFile.delete()) {
1416: // still failed.
1417: System.out.println("ERROR: deleting: " + aFile.getName());
1418: }
1419:
1420: return;
1421:
1422: }
1423:
1424: /* **********************************************
1425: * dumpFileToSysOut:
1426: * Checks to see if the received file is empty,
1427: * and prints a message saying so.
1428: * @param fName Name of the file to be written to output.
1429: * @return The contents of the specified file have
1430: * been written to System.out.
1431: ****/
1432:
1433: private void dumpFileToSysOut(String fName) {
1434:
1435: try {
1436:
1437: BufferedReader dumpFile = new BufferedReader(
1438: new FileReader(fName));
1439:
1440: String line = dumpFile.readLine();
1441: if (line != null) {
1442: System.out
1443: .println("File "
1444: + fName
1445: + " was NOT "
1446: + "empty. Contents are:\n"
1447: + "############## Begin File Contents ################\n");
1448: do {
1449: System.out.println(line);
1450: line = dumpFile.readLine();
1451: } while (line != null);
1452: System.out
1453: .println("############## End File Contents ################");
1454: } else
1455: System.out.println("File " + fName + " was empty.");
1456:
1457: // Close the file.
1458: dumpFile.close();
1459:
1460: } catch (Exception e) {
1461: System.out.println("FAILED: to dump file '" + fName + "'");
1462: e.printStackTrace(System.out);
1463: }
1464:
1465: return;
1466:
1467: }
1468:
1469: /* **********************************************
1470: * isSystemGenerated:
1471: * Returns true if the received string looks like
1472: * it is a system-generated string. We assume
1473: * it's system-generated if either 1) it starts
1474: * with the letters "SQL", in which case it's a
1475: * system-name, or 2) it has a dash in it, in which
1476: * case it's a system id.
1477: * @param str The string to check.
1478: * @return True if we assume the string is system-
1479: * generated, false otherwise.
1480: ****/
1481:
1482: private boolean isSystemGenerated(String str) {
1483:
1484: return (looksLikeSysGenName(str) || looksLikeSysGenId(str));
1485:
1486: }
1487:
1488: /* **********************************************
1489: * looksLikeSysGenName:
1490: * See if the received string looks like it is
1491: * a system-generated name. There are two types
1492: * of system-generated names: 1) visible names,
1493: * which start with "SQL", and 2) hidden names,
1494: * which exist for Stored Statements that are
1495: * used to back triggers; these names start with
1496: * "TRIGGERACTN_" and then have a UUID.
1497: * NOTE: This test assumes that none of object names
1498: * provided in "dblook_makeDB.sql" satisfy
1499: * either of these conditions. If they do, they
1500: * will be filtered out of the test output.
1501: * @param val The string value in question.
1502: * @return True if the value looks like it is a system-
1503: * generated name; false otherwise.
1504: ****/
1505:
1506: private boolean looksLikeSysGenName(String val) {
1507:
1508: return ((val != null) && ((val.trim().indexOf("SQL") == 0) || // case 1.
1509: ((val.trim().indexOf("TRIGGERACTN_") == 0) && // case 2.
1510: (val.indexOf("-") != -1))));
1511:
1512: }
1513:
1514: /* **********************************************
1515: * looksLikeSysGenId:
1516: * See if the received string looks like it is
1517: * a system-generated id (i.e. contains a dash (-)).
1518: * NOTE: This test assumes that none of object names
1519: * provided in "dblook_makeDB.sql" will contain
1520: * dashes. If they do, then they will be filtered out
1521: * in the test output.
1522: * @param val The string value in question.
1523: * @return True if the value looks like it is a system-
1524: * generated id; false otherwise.
1525: ****/
1526:
1527: private boolean looksLikeSysGenId(String val) {
1528:
1529: return ((val != null) && (val.indexOf("-") != -1));
1530:
1531: }
1532:
1533: /* **********************************************
1534: * columnHoldsObjectName:
1535: * Return true if the received column, which is from
1536: * some system table, holds the _name_ of a database
1537: * object (table, constraint, etc.). Typically, we
1538: * can just look for the keyword "NAME"; the exception
1539: * is aliases, where the name is held in a column called
1540: * ALIAS.
1541: * @param colName Name of the column in question.
1542: * @return True if the column name indicates that it
1543: * holds the _name_ of a database object; false if the
1544: * column name indicates that it holds something else.
1545: ****/
1546:
1547: private boolean columnHoldsObjectName(String colName) {
1548:
1549: return (colName.equals("ALIAS") || (colName.indexOf("NAME") != -1));
1550:
1551: }
1552:
1553: /* **********************************************
1554: * printAsHeader:
1555: * Print the received string to output as a
1556: * header.
1557: * @param str String to print.
1558: ****/
1559:
1560: private void printAsHeader(String str) {
1561:
1562: writeOut("--\n*******************************************");
1563: writeOut(str);
1564: writeOut("*******************************************\n");
1565: return;
1566:
1567: }
1568:
1569: }
|