Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
org.apache.hive.beeline.BeeLine Maven / Gradle / Ivy
/*
* Copyright (c) 2002,2003,2004,2005 Marc Prud'hommeaux
* 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 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 THE COPYRIGHT
* OWNER 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.
*
* This software is hosted by SourceForge.
* SourceForge is a trademark of VA Linux Systems, Inc.
*/
/*
* This source file is based on code taken from SQLLine 1.0.2
* The license above originally appeared in src/sqlline/SqlLine.java
* http://sqlline.sourceforge.net/
*/
package org.apache.hive.beeline;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.EOFException;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.net.JarURLConnection;
import java.net.URL;
import java.net.URLConnection;
import java.sql.Connection;
import java.sql.DatabaseMetaData;
import java.sql.Driver;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.SQLWarning;
import java.sql.Statement;
import java.text.ChoiceFormat;
import java.text.MessageFormat;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.SortedSet;
import java.util.StringTokenizer;
import java.util.TreeMap;
import java.util.TreeSet;
import java.util.jar.Attributes;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import jline.ClassNameCompletor;
import jline.Completor;
import jline.ConsoleReader;
import jline.FileNameCompletor;
import jline.SimpleCompletor;
/**
* A console SQL shell with command completion.
*
* TODO:
*
* User-friendly connection prompts
* Page results
* Handle binary data (blob fields)
* Implement command aliases
* Stored procedure execution
* Binding parameters to prepared statements
* Scripting language
* XA transactions
*
*
*/
public class BeeLine {
private static final ResourceBundle resourceBundle =
ResourceBundle.getBundle(BeeLine.class.getName());
private BeeLineSignalHandler signalHandler = null;
private static final String separator = System.getProperty("line.separator");
private boolean exit = false;
private final DatabaseConnections connections = new DatabaseConnections();
public static final String COMMAND_PREFIX = "!";
private final Completor beeLineCommandCompletor;
private Collection drivers = null;
private final BeeLineOpts opts = new BeeLineOpts(this, System.getProperties());
private String lastProgress = null;
private final Map seenWarnings = new HashMap();
private final Commands commands = new Commands(this);
private OutputFile scriptOutputFile = null;
private OutputFile recordOutputFile = null;
private PrintStream outputStream = new PrintStream(System.out, true);
private PrintStream errorStream = new PrintStream(System.err, true);
private ConsoleReader consoleReader;
private List batch = null;
private final Reflector reflector;
public static final String BEELINE_DEFAULT_JDBC_DRIVER = "org.apache.hive.jdbc.HiveDriver";
public static final String BEELINE_DEFAULT_JDBC_URL = "jdbc:hive2://";
private static final String SCRIPT_OUTPUT_PREFIX = ">>>";
private static final int SCRIPT_OUTPUT_PAD_SIZE = 5;
private final Map formats = map(new Object[] {
"vertical", new VerticalOutputFormat(this),
"table", new TableOutputFormat(this),
"csv", new SeparatedValuesOutputFormat(this, ','),
"tsv", new SeparatedValuesOutputFormat(this, '\t'),
"xmlattr", new XMLAttributeOutputFormat(this),
"xmlelements", new XMLElementOutputFormat(this),
});
final CommandHandler[] commandHandlers = new CommandHandler[] {
new ReflectiveCommandHandler(this, new String[] {"quit", "done", "exit"},
null),
new ReflectiveCommandHandler(this, new String[] {"connect", "open"},
new Completor[] {new SimpleCompletor(getConnectionURLExamples())}),
new ReflectiveCommandHandler(this, new String[] {"describe"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"indexes"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"primarykeys"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"exportedkeys"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"manual"},
null),
new ReflectiveCommandHandler(this, new String[] {"importedkeys"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"procedures"},
null),
new ReflectiveCommandHandler(this, new String[] {"tables"},
null),
new ReflectiveCommandHandler(this, new String[] {"typeinfo"},
null),
new ReflectiveCommandHandler(this, new String[] {"columns"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"reconnect"},
null),
new ReflectiveCommandHandler(this, new String[] {"dropall"},
new Completor[] {new TableNameCompletor(this)}),
new ReflectiveCommandHandler(this, new String[] {"history"},
null),
new ReflectiveCommandHandler(this, new String[] {"metadata"},
new Completor[] {
new SimpleCompletor(getMetadataMethodNames())}),
new ReflectiveCommandHandler(this, new String[] {"nativesql"},
null),
new ReflectiveCommandHandler(this, new String[] {"dbinfo"},
null),
new ReflectiveCommandHandler(this, new String[] {"rehash"},
null),
new ReflectiveCommandHandler(this, new String[] {"verbose"},
null),
new ReflectiveCommandHandler(this, new String[] {"run"},
new Completor[] {new FileNameCompletor()}),
new ReflectiveCommandHandler(this, new String[] {"batch"},
null),
new ReflectiveCommandHandler(this, new String[] {"list"},
null),
new ReflectiveCommandHandler(this, new String[] {"all"},
null),
new ReflectiveCommandHandler(this, new String[] {"go", "#"},
null),
new ReflectiveCommandHandler(this, new String[] {"script"},
new Completor[] {new FileNameCompletor()}),
new ReflectiveCommandHandler(this, new String[] {"record"},
new Completor[] {new FileNameCompletor()}),
new ReflectiveCommandHandler(this, new String[] {"brief"},
null),
new ReflectiveCommandHandler(this, new String[] {"close"},
null),
new ReflectiveCommandHandler(this, new String[] {"closeall"},
null),
new ReflectiveCommandHandler(this, new String[] {"isolation"},
new Completor[] {new SimpleCompletor(getIsolationLevels())}),
new ReflectiveCommandHandler(this, new String[] {"outputformat"},
new Completor[] {new SimpleCompletor(
formats.keySet().toArray(new String[0]))}),
new ReflectiveCommandHandler(this, new String[] {"autocommit"},
null),
new ReflectiveCommandHandler(this, new String[] {"commit"},
null),
new ReflectiveCommandHandler(this, new String[] {"properties"},
new Completor[] {new FileNameCompletor()}),
new ReflectiveCommandHandler(this, new String[] {"rollback"},
null),
new ReflectiveCommandHandler(this, new String[] {"help", "?"},
null),
new ReflectiveCommandHandler(this, new String[] {"set"},
getOpts().optionCompletors()),
new ReflectiveCommandHandler(this, new String[] {"save"},
null),
new ReflectiveCommandHandler(this, new String[] {"scan"},
null),
new ReflectiveCommandHandler(this, new String[] {"sql"},
null),
new ReflectiveCommandHandler(this, new String[] {"call"},
null),
};
static final SortedSet KNOWN_DRIVERS = new TreeSet(Arrays.asList(
new String[] {
"org.apache.hive.jdbc.HiveDriver",
"org.apache.hadoop.hive.jdbc.HiveDriver",
}));
static {
try {
Class.forName("jline.ConsoleReader");
} catch (Throwable t) {
throw new ExceptionInInitializerError("jline-missing");
}
}
static Manifest getManifest() throws IOException {
URL base = BeeLine.class.getResource("/META-INF/MANIFEST.MF");
URLConnection c = base.openConnection();
if (c instanceof JarURLConnection) {
return ((JarURLConnection) c).getManifest();
}
return null;
}
String getManifestAttribute(String name) {
try {
Manifest m = getManifest();
if (m == null) {
return "??";
}
Attributes attrs = m.getAttributes("beeline");
if (attrs == null) {
return "???";
}
String val = attrs.getValue(name);
if (val == null || "".equals(val)) {
return "????";
}
return val;
} catch (Exception e) {
e.printStackTrace(errorStream);
return "?????";
}
}
String getApplicationTitle() {
Package pack = BeeLine.class.getPackage();
return loc("app-introduction", new Object[] {
"Beeline",
pack.getImplementationVersion() == null ? "???"
: pack.getImplementationVersion(),
"Apache Hive",
// getManifestAttribute ("Specification-Title"),
// getManifestAttribute ("Implementation-Version"),
// getManifestAttribute ("Implementation-ReleaseDate"),
// getManifestAttribute ("Implementation-Vendor"),
// getManifestAttribute ("Implementation-License"),
});
}
String getApplicationContactInformation() {
return getManifestAttribute("Implementation-Vendor");
}
String loc(String res) {
return loc(res, new Object[0]);
}
String loc(String res, int param) {
try {
return MessageFormat.format(
new ChoiceFormat(resourceBundle.getString(res)).format(param),
new Object[] {new Integer(param)});
} catch (Exception e) {
return res + ": " + param;
}
}
String loc(String res, Object param1) {
return loc(res, new Object[] {param1});
}
String loc(String res, Object param1, Object param2) {
return loc(res, new Object[] {param1, param2});
}
String loc(String res, Object[] params) {
try {
return MessageFormat.format(resourceBundle.getString(res), params);
} catch (Exception e) {
e.printStackTrace(getErrorStream());
try {
return res + ": " + Arrays.asList(params);
} catch (Exception e2) {
return res;
}
}
}
protected String locElapsedTime(long milliseconds) {
if (getOpts().getShowElapsedTime()) {
return loc("time-ms", new Object[] {new Double(milliseconds / 1000d)});
}
return "";
}
/**
* Starts the program.
*/
public static void main(String[] args) throws IOException {
mainWithInputRedirection(args, null);
}
/**
* Starts the program with redirected input. For redirected output,
* setOutputStream() and setErrorStream can be used.
*
* @param args
* same as main()
*
* @param inputStream
* redirected input, or null to use standard input
*/
public static void mainWithInputRedirection(String[] args, InputStream inputStream)
throws IOException {
BeeLine beeLine = new BeeLine();
beeLine.begin(args, inputStream);
// exit the system: useful for Hypersonic and other
// badly-behaving systems
if (!Boolean.getBoolean(BeeLineOpts.PROPERTY_NAME_EXIT)) {
System.exit(0);
}
}
public BeeLine() {
beeLineCommandCompletor = new BeeLineCommandCompletor(this);
reflector = new Reflector(this);
// attempt to dynamically load signal handler
/* TODO disable signal handler
try {
Class> handlerClass =
Class.forName("org.apache.hive.beeline.SunSignalHandler");
signalHandler = (BeeLineSignalHandler)
handlerClass.newInstance();
} catch (Throwable t) {
// ignore and leave cancel functionality disabled
}
*/
}
DatabaseConnection getDatabaseConnection() {
return getDatabaseConnections().current();
}
Connection getConnection() throws SQLException {
if (getDatabaseConnections().current() == null) {
throw new IllegalArgumentException(loc("no-current-connection"));
}
if (getDatabaseConnections().current().getConnection() == null) {
throw new IllegalArgumentException(loc("no-current-connection"));
}
return getDatabaseConnections().current().getConnection();
}
DatabaseMetaData getDatabaseMetaData() {
if (getDatabaseConnections().current() == null) {
throw new IllegalArgumentException(loc("no-current-connection"));
}
if (getDatabaseConnections().current().getDatabaseMetaData() == null) {
throw new IllegalArgumentException(loc("no-current-connection"));
}
return getDatabaseConnections().current().getDatabaseMetaData();
}
public String[] getIsolationLevels() {
return new String[] {
"TRANSACTION_NONE",
"TRANSACTION_READ_COMMITTED",
"TRANSACTION_READ_UNCOMMITTED",
"TRANSACTION_REPEATABLE_READ",
"TRANSACTION_SERIALIZABLE",
};
}
public String[] getMetadataMethodNames() {
try {
TreeSet mnames = new TreeSet();
Method[] m = DatabaseMetaData.class.getDeclaredMethods();
for (int i = 0; m != null && i < m.length; i++) {
mnames.add(m[i].getName());
}
return mnames.toArray(new String[0]);
} catch (Throwable t) {
return new String[0];
}
}
public String[] getConnectionURLExamples() {
return new String[] {
"jdbc:JSQLConnect:///database=",
"jdbc:cloudscape:;create=true",
"jdbc:twtds:sqlserver:///",
"jdbc:daffodilDB_embedded:;create=true",
"jdbc:datadirect:db2://:50000;databaseName=",
"jdbc:inetdae::1433",
"jdbc:datadirect:oracle://:1521;SID=;MaxPooledStatements=0",
"jdbc:datadirect:sqlserver://:1433;SelectMethod=cursor;DatabaseName=",
"jdbc:datadirect:sybase://:5000",
"jdbc:db2:///",
"jdbc:hive2://",
"jdbc:hsqldb:",
"jdbc:idb:.properties",
"jdbc:informix-sqli://:1526/:INFORMIXSERVER=",
"jdbc:interbase:////.gdb",
"jdbc:microsoft:sqlserver://:1433;DatabaseName=;SelectMethod=cursor",
"jdbc:mysql:///?autoReconnect=true",
"jdbc:oracle:thin:@:1521:",
"jdbc:pointbase:,database.home=,create=true",
"jdbc:postgresql://:5432/",
"jdbc:postgresql:net///",
"jdbc:sybase:Tds::4100/?ServiceName=",
"jdbc:weblogic:mssqlserver4:@:1433",
"jdbc:odbc:",
"jdbc:sequelink://:4003/[Oracle]",
"jdbc:sequelink://:4004/[Informix];Database=",
"jdbc:sequelink://:4005/[Sybase];Database=",
"jdbc:sequelink://:4006/[SQLServer];Database=",
"jdbc:sequelink://:4011/[ODBC MS Access];Database=",
"jdbc:openlink:///DSN=SQLServerDB/UID=sa/PWD=",
"jdbc:solid://://",
"jdbc:dbaw://:8889/",
};
}
/**
* Entry point to creating a {@link ColorBuffer} with color
* enabled or disabled depending on the value of {@link BeeLineOpts#getColor}.
*/
ColorBuffer getColorBuffer() {
return new ColorBuffer(getOpts().getColor());
}
/**
* Entry point to creating a {@link ColorBuffer} with color
* enabled or disabled depending on the value of {@link BeeLineOpts#getColor}.
*/
ColorBuffer getColorBuffer(String msg) {
return new ColorBuffer(msg, getOpts().getColor());
}
boolean initArgs(String[] args) {
List commands = new LinkedList();
List files = new LinkedList();
String driver = null, user = null, pass = null, url = null, cmd = null;
for (int i = 0; i < args.length; i++) {
if (args[i].equals("--help") || args[i].equals("-h")) {
usage();
return false;
}
// -- arguments are treated as properties
if (args[i].startsWith("--")) {
String[] parts = split(args[i].substring(2), "=");
debug(loc("setting-prop", Arrays.asList(parts)));
if (parts.length > 0) {
boolean ret;
if (parts.length >= 2) {
ret = getOpts().set(parts[0], parts[1], true);
} else {
ret = getOpts().set(parts[0], "true", true);
}
if (!ret) {
return false;
}
}
continue;
}
if (args[i].equals("-d")) {
driver = args[i++ + 1];
} else if (args[i].equals("-n")) {
user = args[i++ + 1];
} else if (args[i].equals("-p")) {
pass = args[i++ + 1];
} else if (args[i].equals("-u")) {
url = args[i++ + 1];
} else if (args[i].equals("-e")) {
commands.add(args[i++ + 1]);
} else {
files.add(args[i]);
}
}
// TODO: temporary disable this for easier debugging
/*
if (url == null) {
url = BEELINE_DEFAULT_JDBC_URL;
}
if (driver == null) {
driver = BEELINE_DEFAULT_JDBC_DRIVER;
}
*/
if (url != null) {
String com = "!connect "
+ url + " "
+ (user == null || user.length() == 0 ? "''" : user) + " "
+ (pass == null || pass.length() == 0 ? "''" : pass) + " "
+ (driver == null ? "" : driver);
debug("issuing: " + com);
dispatch(com);
}
// now load properties files
for (Iterator i = files.iterator(); i.hasNext();) {
dispatch("!properties " + i.next());
}
if (commands.size() > 0) {
// for single command execute, disable color
getOpts().setColor(false);
getOpts().setHeaderInterval(-1);
for (Iterator i = commands.iterator(); i.hasNext();) {
String command = i.next().toString();
debug(loc("executing-command", command));
dispatch(command);
}
exit = true; // execute and exit
}
return true;
}
/**
* Start accepting input from stdin, and dispatch it
* to the appropriate {@link CommandHandler} until the
* global variable exit
is true.
*/
void begin(String[] args, InputStream inputStream) throws IOException {
try {
// load the options first, so we can override on the command line
getOpts().load();
} catch (Exception e) {
// nothing
}
ConsoleReader reader = getConsoleReader(inputStream);
if (!(initArgs(args))) {
usage();
return;
}
try {
info(getApplicationTitle());
} catch (Exception e) {
// ignore
}
while (!exit) {
try {
dispatch(reader.readLine(getPrompt()));
} catch (EOFException eof) {
// CTRL-D
commands.quit(null);
} catch (Throwable t) {
handleException(t);
}
}
// ### NOTE jvs 10-Aug-2004: Clean up any outstanding
// connections automatically.
commands.closeall(null);
}
public void close() {
commands.quit(null);
commands.closeall(null);
}
public ConsoleReader getConsoleReader(InputStream inputStream) throws IOException {
if (inputStream != null) {
// ### NOTE: fix for sf.net bug 879425.
consoleReader = new ConsoleReader(inputStream, new PrintWriter(System.out, true));
} else {
consoleReader = new ConsoleReader();
}
// setup history
ByteArrayInputStream historyBuffer = null;
if (new File(getOpts().getHistoryFile()).isFile()) {
try {
// save the current contents of the history buffer. This gets
// around a bug in JLine where setting the output before the
// input will clobber the history input, but setting the
// input before the output will cause the previous commands
// to not be saved to the buffer.
FileInputStream historyIn = new FileInputStream(getOpts().getHistoryFile());
ByteArrayOutputStream hist = new ByteArrayOutputStream();
int n;
while ((n = historyIn.read()) != -1) {
hist.write(n);
}
historyIn.close();
historyBuffer = new ByteArrayInputStream(hist.toByteArray());
} catch (Exception e) {
handleException(e);
}
}
try {
// now set the output for the history
PrintWriter historyOut = new PrintWriter(new FileWriter(getOpts().getHistoryFile()), true);
consoleReader.getHistory().setOutput(historyOut);
} catch (Exception e) {
handleException(e);
}
try {
// now load in the previous history
if (historyBuffer != null) {
consoleReader.getHistory().load(historyBuffer);
}
} catch (Exception e) {
handleException(e);
}
consoleReader.addCompletor(new BeeLineCompletor(this));
return consoleReader;
}
void usage() {
output(loc("cmd-usage"));
}
/**
* Dispatch the specified line to the appropriate {@link CommandHandler}.
*
* @param line
* the commmand-line to dispatch
* @return true if the command was "successful"
*/
boolean dispatch(String line) {
if (line == null) {
// exit
exit = true;
return true;
}
if (line.trim().length() == 0) {
return true;
}
if (isComment(line)) {
return true;
}
line = line.trim();
// save it to the current script, if any
if (scriptOutputFile != null) {
scriptOutputFile.addLine(line);
}
if (isHelpRequest(line)) {
line = "!help";
}
if (line.startsWith(COMMAND_PREFIX)) {
Map cmdMap = new TreeMap();
line = line.substring(1);
for (int i = 0; i < commandHandlers.length; i++) {
String match = commandHandlers[i].matches(line);
if (match != null) {
cmdMap.put(match, commandHandlers[i]);
}
}
if (cmdMap.size() == 0) {
return error(loc("unknown-command", line));
} else if (cmdMap.size() > 1) {
return error(loc("multiple-matches",
cmdMap.keySet().toString()));
} else {
return cmdMap.values().iterator().next()
.execute(line);
}
} else {
return commands.sql(line);
}
}
/**
* Test whether a line requires a continuation.
*
* @param line
* the line to be tested
*
* @return true if continuation required
*/
boolean needsContinuation(String line) {
if (isHelpRequest(line)) {
return false;
}
if (line.startsWith(COMMAND_PREFIX)) {
return false;
}
if (isComment(line)) {
return false;
}
String trimmed = line.trim();
if (trimmed.length() == 0) {
return false;
}
return !trimmed.endsWith(";");
}
/**
* Test whether a line is a help request other than !help.
*
* @param line
* the line to be tested
*
* @return true if a help request
*/
boolean isHelpRequest(String line) {
return line.equals("?") || line.equalsIgnoreCase("help");
}
/**
* Test whether a line is a comment.
*
* @param line
* the line to be tested
*
* @return true if a comment
*/
boolean isComment(String line) {
// SQL92 comment prefix is "--"
// beeline also supports shell-style "#" prefix
return line.startsWith("#") || line.startsWith("--");
}
/**
* Print the specified message to the console
*
* @param msg
* the message to print
*/
void output(String msg) {
output(msg, true);
}
void info(String msg) {
if (!(getOpts().isSilent())) {
output(msg, true, getErrorStream());
}
}
void info(ColorBuffer msg) {
if (!(getOpts().isSilent())) {
output(msg, true, getErrorStream());
}
}
/**
* Issue the specified error message
*
* @param msg
* the message to issue
* @return false always
*/
boolean error(String msg) {
output(getColorBuffer().red(msg), true, getErrorStream());
return false;
}
boolean error(Throwable t) {
handleException(t);
return false;
}
void debug(String msg) {
if (getOpts().getVerbose()) {
output(getColorBuffer().blue(msg), true, getErrorStream());
}
}
void output(ColorBuffer msg) {
output(msg, true);
}
void output(String msg, boolean newline, PrintStream out) {
output(getColorBuffer(msg), newline, out);
}
void output(ColorBuffer msg, boolean newline) {
output(msg, newline, getOutputStream());
}
void output(ColorBuffer msg, boolean newline, PrintStream out) {
if (newline) {
out.println(msg.getColor());
} else {
out.print(msg.getColor());
}
if (recordOutputFile == null) {
return;
}
// only write to the record file if we are writing a line ...
// otherwise we might get garbage from backspaces and such.
if (newline) {
recordOutputFile.addLine(msg.getMono()); // always just write mono
} else {
recordOutputFile.print(msg.getMono());
}
}
/**
* Print the specified message to the console
*
* @param msg
* the message to print
* @param newline
* if false, do not append a newline
*/
void output(String msg, boolean newline) {
output(getColorBuffer(msg), newline);
}
void autocommitStatus(Connection c) throws SQLException {
info(loc("autocommit-status", c.getAutoCommit() + ""));
}
/**
* Ensure that autocommit is on for the current connection
*
* @return true if autocommit is set
*/
boolean assertAutoCommit() {
if (!(assertConnection())) {
return false;
}
try {
if (getDatabaseConnection().getConnection().getAutoCommit()) {
return error(loc("autocommit-needs-off"));
}
} catch (Exception e) {
return error(e);
}
return true;
}
/**
* Assert that we have an active, living connection. Print
* an error message if we do not.
*
* @return true if there is a current, active connection
*/
boolean assertConnection() {
try {
if (getDatabaseConnection() == null || getDatabaseConnection().getConnection() == null) {
return error(loc("no-current-connection"));
}
if (getDatabaseConnection().getConnection().isClosed()) {
return error(loc("connection-is-closed"));
}
} catch (SQLException sqle) {
return error(loc("no-current-connection"));
}
return true;
}
/**
* Print out any warnings that exist for the current connection.
*/
void showWarnings() {
try {
if (getDatabaseConnection().getConnection() == null
|| !getOpts().getVerbose()) {
return;
}
showWarnings(getDatabaseConnection().getConnection().getWarnings());
} catch (Exception e) {
handleException(e);
}
}
/**
* Print the specified warning on the console, as well as
* any warnings that are returned from {@link SQLWarning#getNextWarning}.
*
* @param warn
* the {@link SQLWarning} to print
*/
void showWarnings(SQLWarning warn) {
if (warn == null) {
return;
}
if (seenWarnings.get(warn) == null) {
// don't re-display warnings we have already seen
seenWarnings.put(warn, new java.util.Date());
handleSQLException(warn);
}
SQLWarning next = warn.getNextWarning();
if (next != warn) {
showWarnings(next);
}
}
String getPrompt() {
if (getDatabaseConnection() == null || getDatabaseConnection().getUrl() == null) {
return "beeline> ";
} else {
return getPrompt(getDatabaseConnections().getIndex()
+ ": " + getDatabaseConnection().getUrl()) + "> ";
}
}
static String getPrompt(String url) {
if (url == null || url.length() == 0) {
url = "beeline";
}
if (url.indexOf(";") > -1) {
url = url.substring(0, url.indexOf(";"));
}
if (url.indexOf("?") > -1) {
url = url.substring(0, url.indexOf("?"));
}
if (url.length() > 45) {
url = url.substring(0, 45);
}
return url;
}
/**
* Try to obtain the current size of the specified {@link ResultSet} by jumping to the last row
* and getting the row number.
*
* @param rs
* the {@link ResultSet} to get the size for
* @return the size, or -1 if it could not be obtained
*/
int getSize(ResultSet rs) {
try {
if (rs.getType() == rs.TYPE_FORWARD_ONLY) {
return -1;
}
rs.last();
int total = rs.getRow();
rs.beforeFirst();
return total;
} catch (SQLException sqle) {
return -1;
}
// JDBC 1 driver error
catch (AbstractMethodError ame) {
return -1;
}
}
ResultSet getColumns(String table) throws SQLException {
if (!(assertConnection())) {
return null;
}
return getDatabaseConnection().getDatabaseMetaData().getColumns(
getDatabaseConnection().getDatabaseMetaData().getConnection().getCatalog(), null, table, "%");
}
ResultSet getTables() throws SQLException {
if (!(assertConnection())) {
return null;
}
return getDatabaseConnection().getDatabaseMetaData().getTables(
getDatabaseConnection().getDatabaseMetaData().getConnection().getCatalog(), null, "%",
new String[] {"TABLE"});
}
String[] getColumnNames(DatabaseMetaData meta) throws SQLException {
Set names = new HashSet();
info(loc("building-tables"));
try {
ResultSet columns = getColumns("%");
try {
int total = getSize(columns);
int index = 0;
while (columns.next()) {
// add the following strings:
// 1. column name
// 2. table name
// 3. tablename.columnname
progress(index++, total);
String name = columns.getString("TABLE_NAME");
names.add(name);
names.add(columns.getString("COLUMN_NAME"));
names.add(columns.getString("TABLE_NAME") + "."
+ columns.getString("COLUMN_NAME"));
}
progress(index, index);
} finally {
columns.close();
}
info(loc("done"));
return names.toArray(new String[0]);
} catch (Throwable t) {
handleException(t);
return new String[0];
}
}
// //////////////////
// String utilities
// //////////////////
/**
* Split the line into an array by tokenizing on space characters
*
* @param line
* the line to break up
* @return an array of individual words
*/
String[] split(String line) {
return split(line, " ");
}
String dequote(String str) {
if (str == null) {
return null;
}
while ((str.startsWith("'") && str.endsWith("'"))
|| (str.startsWith("\"") && str.endsWith("\""))) {
str = str.substring(1, str.length() - 1);
}
return str;
}
String[] split(String line, String delim) {
StringTokenizer tok = new StringTokenizer(line, delim);
String[] ret = new String[tok.countTokens()];
int index = 0;
while (tok.hasMoreTokens()) {
String t = tok.nextToken();
t = dequote(t);
ret[index++] = t;
}
return ret;
}
static Map map(Object[] obs) {
Map m = new HashMap();
for (int i = 0; i < obs.length - 1; i += 2) {
m.put(obs[i], obs[i + 1]);
}
return Collections.unmodifiableMap(m);
}
static boolean getMoreResults(Statement stmnt) {
try {
return stmnt.getMoreResults();
} catch (Throwable t) {
return false;
}
}
static String xmlattrencode(String str) {
str = replace(str, "\"", """);
str = replace(str, "<", "<");
return str;
}
static String replace(String source, String from, String to) {
if (source == null) {
return null;
}
if (from.equals(to)) {
return source;
}
StringBuilder replaced = new StringBuilder();
int index = -1;
while ((index = source.indexOf(from)) != -1) {
replaced.append(source.substring(0, index));
replaced.append(to);
source = source.substring(index + from.length());
}
replaced.append(source);
return replaced.toString();
}
/**
* Split the line based on spaces, asserting that the
* number of words is correct.
*
* @param line
* the line to split
* @param assertLen
* the number of words to assure
* @param usage
* the message to output if there are an incorrect
* number of words.
* @return the split lines, or null if the assertion failed.
*/
String[] split(String line, int assertLen, String usage) {
String[] ret = split(line);
if (ret.length != assertLen) {
error(usage);
return null;
}
return ret;
}
/**
* Wrap the specified string by breaking on space characters.
*
* @param toWrap
* the string to wrap
* @param len
* the maximum length of any line
* @param start
* the number of spaces to pad at the
* beginning of a line
* @return the wrapped string
*/
String wrap(String toWrap, int len, int start) {
StringBuilder buff = new StringBuilder();
StringBuilder line = new StringBuilder();
char[] head = new char[start];
Arrays.fill(head, ' ');
for (StringTokenizer tok = new StringTokenizer(toWrap, " "); tok.hasMoreTokens();) {
String next = tok.nextToken();
if (line.length() + next.length() > len) {
buff.append(line).append(separator).append(head);
line.setLength(0);
}
line.append(line.length() == 0 ? "" : " ").append(next);
}
buff.append(line);
return buff.toString();
}
/**
* Output a progress indicator to the console.
*
* @param cur
* the current progress
* @param max
* the maximum progress, or -1 if unknown
*/
void progress(int cur, int max) {
StringBuilder out = new StringBuilder();
if (lastProgress != null) {
char[] back = new char[lastProgress.length()];
Arrays.fill(back, '\b');
out.append(back);
}
String progress = cur + "/"
+ (max == -1 ? "?" : "" + max) + " "
+ (max == -1 ? "(??%)"
: ("(" + (cur * 100 / (max == 0 ? 1 : max)) + "%)"));
if (cur >= max && max != -1) {
progress += " " + loc("done") + separator;
lastProgress = null;
} else {
lastProgress = progress;
}
out.append(progress);
outputStream.print(out.toString());
outputStream.flush();
}
// /////////////////////////////
// Exception handling routines
// /////////////////////////////
void handleException(Throwable e) {
while (e instanceof InvocationTargetException) {
e = ((InvocationTargetException) e).getTargetException();
}
if (e instanceof SQLException) {
handleSQLException((SQLException) e);
} else if (!(getOpts().getVerbose())) {
if (e.getMessage() == null) {
error(e.getClass().getName());
} else {
error(e.getMessage());
}
} else {
e.printStackTrace(getErrorStream());
}
}
void handleSQLException(SQLException e) {
if (e instanceof SQLWarning && !(getOpts().getShowWarnings())) {
return;
}
error(loc(e instanceof SQLWarning ? "Warning" : "Error",
new Object[] {
e.getMessage() == null ? "" : e.getMessage().trim(),
e.getSQLState() == null ? "" : e.getSQLState().trim(),
new Integer(e.getErrorCode())}));
if (getOpts().getVerbose()) {
e.printStackTrace(getErrorStream());
}
if (!getOpts().getShowNestedErrs()) {
return;
}
for (SQLException nested = e.getNextException(); nested != null && nested != e; nested = nested
.getNextException()) {
handleSQLException(nested);
}
}
boolean scanForDriver(String url) {
try {
// already registered
if (findRegisteredDriver(url) != null) {
return true;
}
// first try known drivers...
scanDrivers(true);
if (findRegisteredDriver(url) != null) {
return true;
}
// now really scan...
scanDrivers(false);
if (findRegisteredDriver(url) != null) {
return true;
}
return false;
} catch (Exception e) {
debug(e.toString());
return false;
}
}
private Driver findRegisteredDriver(String url) {
for (Enumeration drivers = DriverManager.getDrivers(); drivers != null
&& drivers.hasMoreElements();) {
Driver driver = (Driver) drivers.nextElement();
try {
if (driver.acceptsURL(url)) {
return driver;
}
} catch (Exception e) {
}
}
return null;
}
Driver[] scanDrivers(String line) throws IOException {
return scanDrivers(false);
}
Driver[] scanDrivers(boolean knownOnly) throws IOException {
long start = System.currentTimeMillis();
Set classNames = new HashSet();
if (!knownOnly) {
classNames.addAll(Arrays.asList(
ClassNameCompletor.getClassNames()));
}
classNames.addAll(KNOWN_DRIVERS);
Set driverClasses = new HashSet();
for (Iterator i = classNames.iterator(); i.hasNext();) {
String className = i.next().toString();
if (className.toLowerCase().indexOf("driver") == -1) {
continue;
}
try {
Class c = Class.forName(className, false,
Thread.currentThread().getContextClassLoader());
if (!Driver.class.isAssignableFrom(c)) {
continue;
}
if (Modifier.isAbstract(c.getModifiers())) {
continue;
}
// now instantiate and initialize it
driverClasses.add(c.newInstance());
} catch (Throwable t) {
}
}
info("scan complete in "
+ (System.currentTimeMillis() - start) + "ms");
return (Driver[]) driverClasses.toArray(new Driver[0]);
}
private Driver[] scanDriversOLD(String line) {
long start = System.currentTimeMillis();
Set paths = new HashSet();
Set driverClasses = new HashSet();
for (StringTokenizer tok = new StringTokenizer(
System.getProperty("java.ext.dirs"),
System.getProperty("path.separator")); tok.hasMoreTokens();) {
File[] files = new File(tok.nextToken()).listFiles();
for (int i = 0; files != null && i < files.length; i++) {
paths.add(files[i].getAbsolutePath());
}
}
for (StringTokenizer tok = new StringTokenizer(
System.getProperty("java.class.path"),
System.getProperty("path.separator")); tok.hasMoreTokens();) {
paths.add(new File(tok.nextToken()).getAbsolutePath());
}
for (Iterator i = paths.iterator(); i.hasNext();) {
File f = new File(i.next());
output(getColorBuffer().pad(loc("scanning", f.getAbsolutePath()), 60),
false);
try {
ZipFile zf = new ZipFile(f);
int total = zf.size();
int index = 0;
for (Enumeration zfEnum = zf.entries(); zfEnum.hasMoreElements();) {
ZipEntry entry = (ZipEntry) zfEnum.nextElement();
String name = entry.getName();
progress(index++, total);
if (name.endsWith(".class")) {
name = name.replace('/', '.');
name = name.substring(0, name.length() - 6);
try {
// check for the string "driver" in the class
// to see if we should load it. Not perfect, but
// it is far too slow otherwise.
if (name.toLowerCase().indexOf("driver") != -1) {
Class c = Class.forName(name, false,
getClass().getClassLoader());
if (Driver.class.isAssignableFrom(c)
&& !(Modifier.isAbstract(
c.getModifiers()))) {
try {
// load and initialize
Class.forName(name);
} catch (Exception e) {
}
driverClasses.add(c.newInstance());
}
}
} catch (Throwable t) {
}
}
}
progress(total, total);
} catch (Exception e) {
}
}
info("scan complete in "
+ (System.currentTimeMillis() - start) + "ms");
return (Driver[]) driverClasses.toArray(new Driver[0]);
}
// /////////////////////////////////////
// ResultSet output formatting classes
// /////////////////////////////////////
int print(ResultSet rs) throws SQLException {
String format = getOpts().getOutputFormat();
OutputFormat f = (OutputFormat) formats.get(format);
if (f == null) {
error(loc("unknown-format", new Object[] {
format, formats.keySet()}));
f = new TableOutputFormat(this);
}
Rows rows;
if (getOpts().getIncremental()) {
rows = new IncrementalRows(this, rs);
} else {
rows = new BufferedRows(this, rs);
}
return f.print(rows);
}
Statement createStatement() throws SQLException {
Statement stmnt = getDatabaseConnection().getConnection().createStatement();
if (getOpts().timeout > -1) {
stmnt.setQueryTimeout(getOpts().timeout);
}
if (signalHandler != null) {
signalHandler.setStatement(stmnt);
}
return stmnt;
}
void runBatch(List statements) {
try {
Statement stmnt = createStatement();
try {
for (Iterator i = statements.iterator(); i.hasNext();) {
stmnt.addBatch(i.next().toString());
}
int[] counts = stmnt.executeBatch();
output(getColorBuffer().pad(getColorBuffer().bold("COUNT"), 8)
.append(getColorBuffer().bold("STATEMENT")));
for (int i = 0; counts != null && i < counts.length; i++) {
output(getColorBuffer().pad(counts[i] + "", 8)
.append(statements.get(i).toString()));
}
} finally {
try {
stmnt.close();
} catch (Exception e) {
}
}
} catch (Exception e) {
handleException(e);
}
}
public int runCommands(String[] cmds) {
return runCommands(Arrays.asList(cmds));
}
public int runCommands(List cmds) {
int successCount = 0;
try {
// TODO: Make script output prefixing configurable. Had to disable this since
// it results in lots of test diffs.
for (String cmd : cmds) {
info(getColorBuffer().pad(SCRIPT_OUTPUT_PREFIX, SCRIPT_OUTPUT_PAD_SIZE).append(cmd));
// if we do not force script execution, abort
// when a failure occurs.
if (dispatch(cmd) || getOpts().getForce()) {
++successCount;
} else {
error(loc("abort-on-error", cmd));
return successCount;
}
}
} catch (Exception e) {
handleException(e);
}
return successCount;
}
// ////////////////////////
// Command methods follow
// ////////////////////////
void setCompletions() throws SQLException, IOException {
if (getDatabaseConnection() != null) {
getDatabaseConnection().setCompletions(getOpts().getFastConnect());
}
}
BeeLineOpts getOpts() {
return opts;
}
DatabaseConnections getDatabaseConnections() {
return connections;
}
Completor getCommandCompletor() {
return beeLineCommandCompletor;
}
public boolean isExit() {
return exit;
}
public void setExit(boolean exit) {
this.exit = exit;
}
Collection getDrivers() {
return drivers;
}
void setDrivers(Collection drivers) {
this.drivers = drivers;
}
public static String getSeparator() {
return separator;
}
Commands getCommands() {
return commands;
}
OutputFile getScriptOutputFile() {
return scriptOutputFile;
}
void setScriptOutputFile(OutputFile script) {
this.scriptOutputFile = script;
}
OutputFile getRecordOutputFile() {
return recordOutputFile;
}
void setRecordOutputFile(OutputFile record) {
this.recordOutputFile = record;
}
public void setOutputStream(PrintStream outputStream) {
this.outputStream = new PrintStream(outputStream, true);
}
PrintStream getOutputStream() {
return outputStream;
}
public void setErrorStream(PrintStream errorStream) {
this.errorStream = new PrintStream(errorStream, true);
}
PrintStream getErrorStream() {
return errorStream;
}
ConsoleReader getConsoleReader() {
return consoleReader;
}
void setConsoleReader(ConsoleReader reader) {
this.consoleReader = reader;
}
List getBatch() {
return batch;
}
void setBatch(List batch) {
this.batch = batch;
}
protected Reflector getReflector() {
return reflector;
}
}