📄 sqltool.java
字号:
/* Copyright (c) 2001-2008, The HSQL Development Group
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* Neither the name of the HSQL Development Group nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL HSQL DEVELOPMENT GROUP, HSQLDB.ORG,
* OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
* PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
package org.hsqldb.util;
import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.Map;
/* $Id: SqlTool.java,v 1.73 2008/03/15 13:53:47 fredt Exp $ */
/**
* Sql Tool. A command-line and/or interactive SQL tool.
* (Note: For every Javadoc block comment, I'm using a single blank line
* immediately after the description, just like's Sun's examples in
* their Coding Conventions document).
*
* See JavaDocs for the main method for syntax of how to run.
* This class is mostly used in a static (a.o.t. object) way, because most
* of the work is done in the static main class.
* This class should be refactored so that the main work is done in an
* object method, and the static main invokes the object method.
* Then programmatic users could use instances of this class in the normal
* Java way.
*
* @see #main()
* @version $Revision: 1.73 $
* @author Blaine Simpson unsaved@users
*/
public class SqlTool {
private static final String DEFAULT_RCFILE =
System.getProperty("user.home") + "/sqltool.rc";
// N.b. the following is static!
private static String revnum = null;
public static final int SQLTOOLERR_EXITVAL = 1;
public static final int SYNTAXERR_EXITVAL = 11;
public static final int RCERR_EXITVAL = 2;
public static final int SQLERR_EXITVAL = 3;
public static final int IOERR_EXITVAL = 4;
public static final int FILEERR_EXITVAL = 5;
public static final int INPUTERR_EXITVAL = 6;
public static final int CONNECTERR_EXITVAL = 7;
/**
* The configuration identifier to use when connection parameters are
* specified on the command line
*/
private static String CMDLINE_ID = "cmdline";
static private SqltoolRB rb = null;
// Must use a shared static RB object, since we need to get messages
// inside of static methods.
// This means that the locale will be set the first time this class
// is accessed. Subsequent calls will not update the RB if the locale
// changes (could have it check and reload the RB if this becomes an
// issue).
static {
revnum = "333";
try {
rb = new SqltoolRB();
rb.validate();
rb.setMissingPosValueBehavior(
ValidatingResourceBundle.NOOP_BEHAVIOR);
rb.setMissingPropertyBehavior(
ValidatingResourceBundle.NOOP_BEHAVIOR);
} catch (RuntimeException re) {
System.err.println("Failed to initialize resource bundle");
throw re;
}
}
public static String LS = System.getProperty("line.separator");
/** Utility nested class for internal use. */
private static class BadCmdline extends Exception {
static final long serialVersionUID = -2134764796788108325L;
BadCmdline() {}
}
/** Utility object for internal use. */
private static BadCmdline bcl = new BadCmdline();
/** For trapping of exceptions inside this class.
* These are always handled inside this class.
*/
private static class PrivateException extends Exception {
static final long serialVersionUID = -7765061479594523462L;
PrivateException() {
super();
}
PrivateException(String s) {
super(s);
}
}
public static class SqlToolException extends Exception {
static final long serialVersionUID = 1424909871915188519L;
int exitValue = 1;
SqlToolException(String message, int exitValue) {
super(message);
this.exitValue = exitValue;
}
SqlToolException(int exitValue, String message) {
this(message, exitValue);
}
SqlToolException(int exitValue) {
super();
this.exitValue = exitValue;
}
}
/**
* Prompt the user for a password.
*
* @param username The user the password is for
* @return The password the user entered
*/
private static String promptForPassword(String username)
throws PrivateException {
BufferedReader console;
String password;
password = null;
try {
console = new BufferedReader(new InputStreamReader(System.in));
// Prompt for password
System.out.print(rb.getString(SqltoolRB.PASSWORDFOR_PROMPT,
RCData.expandSysPropVars(username)));
// Read the password from the command line
password = console.readLine();
if (password == null) {
password = "";
} else {
password = password.trim();
}
} catch (IOException e) {
throw new PrivateException(e.getMessage());
}
return password;
}
/**
* Parses a comma delimited string of name value pairs into a
* <code>Map</code> object.
*
* @param varString The string to parse
* @param varMap The map to save the paired values into
* @param lowerCaseKeys Set to <code>true</code> if the map keys should be
* converted to lower case
*/
private static void varParser(String varString, Map varMap,
boolean lowerCaseKeys)
throws PrivateException {
int equals;
String var;
String val;
String[] allvars;
if ((varMap == null) || (varString == null)) {
throw new IllegalArgumentException(
"varMap or varString are null in SqlTool.varParser call");
}
allvars = varString.split("\\s*,\\s*");
for (int i = 0; i < allvars.length; i++) {
equals = allvars[i].indexOf('=');
if (equals < 1) {
throw new PrivateException(
rb.getString(SqltoolRB.SQLTOOL_VARSET_BADFORMAT));
}
var = allvars[i].substring(0, equals).trim();
val = allvars[i].substring(equals + 1).trim();
if (var.length() < 1) {
throw new PrivateException(
rb.getString(SqltoolRB.SQLTOOL_VARSET_BADFORMAT));
}
if (lowerCaseKeys) {
var = var.toLowerCase();
}
varMap.put(var, val);
}
}
/**
* A static wrapper for objectMain, so that that method may be executed
* as a Java "program".
*
* Throws only RuntimExceptions or Errors, because this method is intended
* to System.exit() for all but disasterous system problems, for which
* the inconvenience of a a stack trace would be the least of your worries.
*
* If you don't want SqlTool to System.exit(), then use the method
* objectMain() instead of this method.
*
* @see objectMain(String[])
*/
public static void main(String[] args) {
try {
SqlTool.objectMain(args);
} catch (SqlToolException fr) {
if (fr.getMessage() != null) {
System.err.println(fr.getMessage());
}
System.exit(fr.exitValue);
}
System.exit(0);
}
/**
* Connect to a JDBC Database and execute the commands given on
* stdin or in SQL file(s).
*
* This method is changed for HSQLDB 1.8.0.8 and 1.9.0.x to never
* System.exit().
*
* @param arg Run "java... org.hsqldb.util.SqlTool --help" for syntax.
* @throws SqlToolException Upon any fatal error, with useful
* reason as the exception's message.
*/
static public void objectMain(String[] arg) throws SqlToolException {
/*
* The big picture is, we parse input args; load a RCData;
* get a JDBC Connection with the RCData; instantiate and
* execute as many SqlFiles as we need to.
*/
String rcFile = null;
File tmpFile = null;
String sqlText = null;
String driver = null;
String targetDb = null;
String varSettings = null;
boolean debug = false;
File[] scriptFiles = null;
int i = -1;
boolean listMode = false;
boolean interactive = false;
boolean noinput = false;
boolean noautoFile = false;
boolean autoCommit = false;
Boolean coeOverride = null;
Boolean stdinputOverride = null;
String rcParams = null;
String rcUrl = null;
String rcUsername = null;
String rcPassword = null;
String rcCharset = null;
String rcTruststore = null;
Map rcFields = null;
String parameter;
try {
while ((i + 1 < arg.length) && arg[i + 1].startsWith("--")) {
i++;
if (arg[i].length() == 2) {
break; // "--"
}
parameter = arg[i].substring(2).toLowerCase();
if (parameter.equals("help")) {
System.out.println(rb.getString(SqltoolRB.SQLTOOL_SYNTAX,
revnum, RCData.DEFAULT_JDBC_DRIVER));
return;
}
if (parameter.equals("abortonerr")) {
if (coeOverride != null) {
throw new SqlToolException(SYNTAXERR_EXITVAL,
rb.getString(
SqltoolRB.SQLTOOL_ABORTCONTINUE_MUTUALLYEXCLUSIVE));
}
coeOverride = Boolean.FALSE;
} else if (parameter.equals("continueonerr")) {
if (coeOverride != null) {
throw new SqlToolException(SYNTAXERR_EXITVAL,
rb.getString(
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -