Index: jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveStatement.java =================================================================== --- jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveStatement.java (revision 807721) +++ jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveStatement.java Thu Aug 27 12:05:48 PDT 2009 @@ -24,6 +24,7 @@ import java.sql.SQLWarning; import java.util.Vector; import org.apache.hadoop.hive.service.HiveInterface; +import org.apache.hadoop.hive.service.HiveServerException; public class HiveStatement implements java.sql.Statement { JdbcSessionState session; @@ -167,9 +168,13 @@ try { this.resultSet = null; client.execute(sql); - } catch (Exception ex) { - throw new SQLException(ex.toString()); - } + } + catch (HiveServerException e) { + throw new SQLException(e.getMessage(), e.getSQLState(), e.getErrorCode()); + } + catch (Exception ex) { + throw new SQLException(ex.toString(), "08S01"); + } this.resultSet = new HiveResultSet(client, maxRows); return this.resultSet; } Index: jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveDatabaseMetaData.java =================================================================== --- jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveDatabaseMetaData.java (revision 807721) +++ jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveDatabaseMetaData.java Tue Aug 25 14:29:31 PDT 2009 @@ -22,6 +22,7 @@ import java.sql.ResultSet; import java.sql.RowIdLifetime; import java.sql.SQLException; +import java.sql.DatabaseMetaData; import java.net.URL; import java.util.jar.Manifest; import java.util.jar.Attributes; @@ -619,8 +620,7 @@ */ public int getSQLStateType() throws SQLException { - // TODO Auto-generated method stub - throw new SQLException("Method not supported"); + return DatabaseMetaData.sqlStateSQL99; } /* (non-Javadoc) Index: conf/hive-log4j.properties =================================================================== --- conf/hive-log4j.properties (revision 807721) +++ conf/hive-log4j.properties Wed Aug 12 09:47:58 PDT 2009 @@ -1,5 +1,5 @@ # Define some default values that can be overridden by system properties -hive.root.logger=WARN,DRFA +hive.root.logger=DEBUG,DRFA hive.log.dir=/tmp/${user.name} hive.log.file=hive.log Index: service/src/gen-javabean/org/apache/hadoop/hive/service/HiveServerException.java =================================================================== --- service/src/gen-javabean/org/apache/hadoop/hive/service/HiveServerException.java (revision 807721) +++ service/src/gen-javabean/org/apache/hadoop/hive/service/HiveServerException.java Wed Aug 26 17:35:22 PDT 2009 @@ -5,14 +5,9 @@ */ package org.apache.hadoop.hive.service; -import java.util.List; -import java.util.ArrayList; import java.util.Map; import java.util.HashMap; -import java.util.Set; -import java.util.HashSet; import java.util.Collections; -import org.apache.log4j.Logger; import org.apache.thrift.*; import org.apache.thrift.meta_data.*; @@ -21,10 +16,18 @@ public class HiveServerException extends Exception implements TBase, java.io.Serializable, Cloneable { private static final TStruct STRUCT_DESC = new TStruct("HiveServerException"); private static final TField MESSAGE_FIELD_DESC = new TField("message", TType.STRING, (short)1); + private static final TField ERROR_CODE_FIELD_DESC = new TField("errorCode", TType.I32, (short)2); + private static final TField SQL_STATE_FIELD_DESC = new TField("SQLState", TType.STRING, (short)3); private String message; public static final int MESSAGE = 1; + private int errorCode = -1; + public static final int ERROR_CODE = 2; + + private String SQLState; + public static final int SQL_STATE = 3; + private final Isset __isset = new Isset(); private static final class Isset implements java.io.Serializable { } @@ -32,6 +35,10 @@ public static final Map metaDataMap = Collections.unmodifiableMap(new HashMap() {{ put(MESSAGE, new FieldMetaData("message", TFieldRequirementType.DEFAULT, new FieldValueMetaData(TType.STRING))); + put(ERROR_CODE, new FieldMetaData("errorCode", TFieldRequirementType.DEFAULT, + new FieldValueMetaData(TType.I32))); + put(SQL_STATE, new FieldMetaData("SQLState", TFieldRequirementType.DEFAULT, + new FieldValueMetaData(TType.STRING))); }}); static { @@ -44,8 +51,16 @@ public HiveServerException( String message) { + this(message, -1, null); + } + + public HiveServerException( + String message, int errorCode, String SQLState) + { this(); this.message = message; + this.errorCode = errorCode; + this.SQLState = SQLState; } /** @@ -54,6 +69,8 @@ public HiveServerException(HiveServerException other) { if (other.isSetMessage()) { this.message = other.message; + this.errorCode = other.errorCode; + this.SQLState = other.SQLState; } } @@ -79,6 +96,40 @@ return this.message != null; } + public int getErrorCode() { + return this.errorCode; + } + + public void setErrorCode(int errorCode) { + this.errorCode = errorCode; + } + + public void unsetErrorCode() { + this.errorCode = -1; + } + + // Returns true if field errorCode is set (has been asigned a value) and false otherwise + public boolean isSetErrorCode() { + return this.errorCode != -1; + } + + public String getSQLState() { + return this.SQLState; + } + + public void setSQLState(String SQLState) { + this.SQLState = SQLState; + } + + public void unsetSQLState() { + this.SQLState = null; + } + + // Returns true if field SQLState is set (has been asigned a value) and false otherwise + public boolean isSetSQLState() { + return this.SQLState != null; + } + public void setFieldValue(int fieldID, Object value) { switch (fieldID) { case MESSAGE: @@ -88,6 +139,20 @@ setMessage((String)value); } break; + case ERROR_CODE: + if (value == null) { + unsetErrorCode(); + } else { + setErrorCode((Integer)value); + } + break; + case SQL_STATE: + if (value == null) { + unsetSQLState(); + } else { + setSQLState((String)value); + } + break; default: throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); @@ -98,6 +163,10 @@ switch (fieldID) { case MESSAGE: return getMessage(); + case ERROR_CODE: + return getErrorCode(); + case SQL_STATE: + return getSQLState(); default: throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); @@ -109,6 +178,10 @@ switch (fieldID) { case MESSAGE: return isSetMessage(); + case ERROR_CODE: + return isSetErrorCode(); + case SQL_STATE: + return isSetSQLState(); default: throw new IllegalArgumentException("Field " + fieldID + " doesn't exist!"); } @@ -136,6 +209,24 @@ return false; } + boolean this_present_error_code = true && this.isSetErrorCode(); + boolean that_present_error_code = true && that.isSetErrorCode(); + if (this_present_error_code || that_present_error_code) { + if (!(this_present_error_code && that_present_error_code)) + return false; + if (this.errorCode != that.errorCode) + return false; + } + + boolean this_present_sql_state = true && this.isSetSQLState(); + boolean that_present_sql_state = true && that.isSetSQLState(); + if (this_present_sql_state || that_present_sql_state) { + if (!(this_present_sql_state && that_present_sql_state)) + return false; + if (this.SQLState != that.SQLState) + return false; + } + return true; } @@ -162,6 +253,20 @@ TProtocolUtil.skip(iprot, field.type); } break; + case ERROR_CODE: + if (field.type == TType.I32) { + this.errorCode = iprot.readI32(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; + case SQL_STATE: + if (field.type == TType.STRING) { + this.SQLState = iprot.readString(); + } else { + TProtocolUtil.skip(iprot, field.type); + } + break; default: TProtocolUtil.skip(iprot, field.type); break; @@ -182,6 +287,16 @@ oprot.writeString(this.message); oprot.writeFieldEnd(); } + if (this.errorCode != -1) { + oprot.writeFieldBegin(ERROR_CODE_FIELD_DESC); + oprot.writeI32(this.errorCode); + oprot.writeFieldEnd(); + } + if (this.SQLState != null) { + oprot.writeFieldBegin(SQL_STATE_FIELD_DESC); + oprot.writeString(this.SQLState); + oprot.writeFieldEnd(); + } oprot.writeFieldStop(); oprot.writeStructEnd(); } @@ -197,6 +312,17 @@ } else { sb.append(this.message); } + + sb.append(",errorCode:"); + sb.append(this.errorCode); + + sb.append(",SQLState:"); + if (this.SQLState == null) { + sb.append("null"); + } else { + sb.append(this.SQLState); + } + first = false; sb.append(")"); return sb.toString(); Index: jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveConnection.java =================================================================== --- jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveConnection.java (revision 807721) +++ jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveConnection.java Wed Aug 26 17:25:04 PDT 2009 @@ -43,8 +43,8 @@ import org.apache.thrift.protocol.TBinaryProtocol; import org.apache.thrift.transport.TSocket; import org.apache.thrift.transport.TTransport; -import org.apache.hadoop.hive.conf.HiveConf; -import java.net.URI; +import org.apache.thrift.transport.TTransportException; +import org.apache.hadoop.hive.metastore.api.MetaException; public class HiveConnection implements java.sql.Connection { JdbcSessionState session; @@ -56,25 +56,32 @@ private static final String URI_PREFIX = "jdbc:hive://"; /** - * TODO: - throw more specific exception - * - parse uri (use java.net.URI?) + * TODO: - parse uri (use java.net.URI?) */ - public HiveConnection(String uri, Properties info) throws Exception { + public HiveConnection(String uri, Properties info) throws SQLException { session = new JdbcSessionState(new HiveConf(SessionState.class)); session.in = null; session.out = null; session.err = null; SessionState.start(session); + String originalUri = uri; if (!uri.startsWith(URI_PREFIX)) { - throw new Exception("Invalid URL: " + uri); + throw new SQLException("Invalid URL: " + uri, "08S01"); } + // remove prefix uri = uri.substring(URI_PREFIX.length()); // If uri is not specified, use local mode. if (uri.isEmpty()) { + try { - client = new HiveServer.HiveServerHandler(); + client = new HiveServer.HiveServerHandler(); + } + catch (MetaException e) { + throw new SQLException("Error accessing Hive metastore: " + + e.getMessage(), "08S01"); + } } else { // parse uri // form: hostname:port/databasename @@ -92,8 +99,14 @@ transport = new TSocket(host, port); TProtocol protocol = new TBinaryProtocol(transport); client = new HiveClient(protocol); + try { - transport.open(); - } + transport.open(); + } + catch (TTransportException e) { + throw new SQLException("Could not establish connecton to " + + originalUri + ": " + e.getMessage(), "08S01"); + } + } isClosed = false; } Index: jdbc/src/test/org/apache/hadoop/hive/jdbc/TestJdbcDriver.java =================================================================== --- jdbc/src/test/org/apache/hadoop/hive/jdbc/TestJdbcDriver.java (revision 807721) +++ jdbc/src/test/org/apache/hadoop/hive/jdbc/TestJdbcDriver.java Wed Aug 26 17:25:04 PDT 2009 @@ -199,6 +199,57 @@ assertTrue("Statement should be closed", stmt.isClosed()); } + public void testErrorMessages() throws SQLException { + String invalidSyntaxSQLState = "42000"; + int parseErrorCode = 10; + + //These tests inherently cause exceptions to be written to the test output + //logs. This is undesirable, since you it might appear to someone looking + //at the test output logs as if something is failing when it isn't. Not sure + //how to get around that. + doTestErrorCase("SELECTT * FROM " + tableName, + "cannot recognize input 'SELECTT'", + invalidSyntaxSQLState, 11); + doTestErrorCase("SELECT * FROM some_table_that_does_not_exist", + "Table not found", "42S02", parseErrorCode); + doTestErrorCase("drop table some_table_that_does_not_exist", + "Table not found", "42S02", parseErrorCode); + doTestErrorCase("SELECT invalid_column FROM " + tableName, + "Invalid Table Alias or Column Reference", + invalidSyntaxSQLState, parseErrorCode); + doTestErrorCase("SELECT invalid_function(key) FROM " + tableName, + "Invalid Function", invalidSyntaxSQLState, parseErrorCode); + + //TODO: execute errors like this currently don't return good messages (i.e. + //'Table already exists'). This is because the Driver class calls + //Task.executeTask() which swallows meaningful exceptions and returns a status + //code. This should be refactored. + doTestErrorCase("create table " + tableName + " (key int, value string)", + "Query returned non-zero code: 9, cause: FAILED: Execution Error, return code 1 from org.apache.hadoop.hive.ql.exec.DDLTask", + "08S01", 9); + } + + private void doTestErrorCase(String sql, String expectedMessage, + String expectedSQLState, + int expectedErrorCode) throws SQLException { + Statement stmt = con.createStatement(); + boolean exceptionFound = false; + try { + stmt.executeQuery(sql); + } + catch(SQLException e) { + assertTrue("Adequate error messaging not found for '" + sql + "': " + + e.getMessage(), e.getMessage().contains(expectedMessage)); + assertEquals("Expected SQLState not found for '" + sql + "'", + expectedSQLState, e.getSQLState()); + assertEquals("Expected error code not found for '" + sql + "'", + expectedErrorCode, e.getErrorCode()); + exceptionFound = true; + } + + assertNotNull("Exception should have been thrown for query: " + sql, exceptionFound); + } + public void testShowTables() throws SQLException { Statement stmt = con.createStatement(); assertNotNull("Statement is null", stmt); @@ -239,6 +290,7 @@ assertEquals("Hive", meta.getDatabaseProductName()); assertEquals("0", meta.getDatabaseProductVersion()); + assertEquals(DatabaseMetaData.sqlStateSQL99, meta.getSQLStateType()); assertNull(meta.getProcedures(null, null, null)); assertFalse(meta.supportsCatalogsInTableDefinitions()); assertFalse(meta.supportsSchemasInTableDefinitions()); Index: jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveDriver.java =================================================================== --- jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveDriver.java (revision 807721) +++ jdbc/src/java/org/apache/hadoop/hive/jdbc/HiveDriver.java Wed Aug 26 16:52:39 PDT 2009 @@ -105,12 +105,8 @@ public Connection connect(String url, Properties info) throws SQLException { - try { - return new HiveConnection(url, info); + return new HiveConnection(url, info); - } catch (Exception ex) { - throw new SQLException(ex.toString()); - } + } - } /** * Returns the major version of this driver. Index: ql/src/java/org/apache/hadoop/hive/ql/Driver.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/Driver.java (revision 807721) +++ ql/src/java/org/apache/hadoop/hive/ql/Driver.java Wed Aug 26 17:33:22 PDT 2009 @@ -35,6 +35,7 @@ import org.apache.hadoop.hive.ql.parse.ParseException; import org.apache.hadoop.hive.ql.parse.BaseSemanticAnalyzer; import org.apache.hadoop.hive.ql.parse.SemanticAnalyzerFactory; +import org.apache.hadoop.hive.ql.parse.ErrorMsg; import org.apache.hadoop.hive.ql.session.SessionState; import org.apache.hadoop.hive.ql.session.SessionState.LogHelper; import org.apache.hadoop.hive.ql.exec.ExecDriver; @@ -69,6 +70,8 @@ private DataInput resStream; private Context ctx; private QueryPlan plan; + private String errorMessage; + private String SQLState; public int countJobs(List> tasks) { return countJobs(tasks, new ArrayList>()); @@ -255,16 +258,21 @@ plan = new QueryPlan(command, sem); return (0); } catch (SemanticException e) { - console.printError("FAILED: Error in semantic analysis: " - + e.getMessage(), "\n" + errorMessage = "FAILED: Error in semantic analysis: " + e.getMessage(); + SQLState = ErrorMsg.findSQLState(e.getMessage()); + console.printError(errorMessage, "\n" + org.apache.hadoop.util.StringUtils.stringifyException(e)); return (10); } catch (ParseException e) { - console.printError("FAILED: Parse Error: " + e.getMessage(), "\n" + errorMessage = "FAILED: Parse Error: " + e.getMessage(); + SQLState = ErrorMsg.findSQLState(e.getMessage()); + console.printError(errorMessage, "\n" + org.apache.hadoop.util.StringUtils.stringifyException(e)); return (11); } catch (Exception e) { - console.printError("FAILED: Unknown exception : " + e.getMessage(), "\n" + errorMessage = "FAILED: Unknown exception: " + e.getMessage(); + SQLState = ErrorMsg.findSQLState(e.getMessage()); + console.printError(errorMessage, "\n" + org.apache.hadoop.util.StringUtils.stringifyException(e)); return (12); } @@ -276,15 +284,52 @@ public QueryPlan getPlan() { return plan; } - + public int run(String command) { + DriverResponse response = runCommand(command); + return response.getResponseCode(); + } + + public DriverResponse runCommand(String command) { + errorMessage = null; + SQLState = null; + int ret = compile(command); if (ret != 0) - return (ret); + return new DriverResponse(ret, errorMessage, SQLState); - return execute(); + ret = execute(); + if (ret != 0) + return new DriverResponse(ret, errorMessage, SQLState); + + return new DriverResponse(ret); } + /** + * Encapsulates the basic response info returned by the Driver. Typically + * errorMessage and SQLState will only be set if + * the responseCode is not 0. + */ + public class DriverResponse { + private int responseCode; + private String errorMessage; + private String SQLState; + + public DriverResponse(int responseCode) { + this(responseCode, null, null); + } + + public DriverResponse(int responseCode, String errorMessage, String SQLState) { + this.responseCode = responseCode; + this.errorMessage = errorMessage; + this.SQLState = SQLState; + } + + public int getResponseCode() { return responseCode; } + public String getErrorMessage() { return errorMessage; } + public String getSQLState() { return SQLState; } + } + private List getPreExecHooks() throws Exception { ArrayList pehooks = new ArrayList(); String pestr = conf.getVar(HiveConf.ConfVars.PREEXECHOOKS); @@ -384,8 +429,11 @@ SessionState.get().getHiveHistory().endTask(queryId, tsk); } if (exitVal != 0) { - console.printError("FAILED: Execution Error, return code " + exitVal - + " from " + tsk.getClass().getName()); + //TODO: This error messaging is not very informative. Fix that. + errorMessage = "FAILED: Execution Error, return code " + exitVal + + " from " + tsk.getClass().getName(); + SQLState = "08S01"; + console.printError(errorMessage); return 9; } @@ -413,7 +461,10 @@ if (SessionState.get() != null) SessionState.get().getHiveHistory().setQueryProperty(queryId, Keys.QUERY_RET_CODE, String.valueOf(12)); - console.printError("FAILED: Unknown exception : " + e.getMessage(), "\n" + //TODO: do better with handling types of Exception here + errorMessage = "FAILED: Unknown exception : " + e.getMessage(); + SQLState = "08S01"; + console.printError(errorMessage, "\n" + org.apache.hadoop.util.StringUtils.stringifyException(e)); return (12); } finally { Index: ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java =================================================================== --- ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java (revision 807721) +++ ql/src/java/org/apache/hadoop/hive/ql/parse/ErrorMsg.java Wed Aug 26 16:12:56 PDT 2009 @@ -20,13 +20,25 @@ import org.antlr.runtime.tree.*; +import java.util.Map; +import java.util.HashMap; +import java.util.regex.Pattern; +import java.util.regex.Matcher; + /** * List of error messages thrown by the parser **/ public enum ErrorMsg { + //SQLStates are taken from Section 12.5 of ISO-9075. + //See http://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt + //Most will just rollup to the generic syntax error state of 42000, but + //specific errors can override the that state. + //See this page for how MySQL uses SQLState codes: + //http://dev.mysql.com/doc/refman/5.0/en/connector-j-reference-error-sqlstates.html + GENERIC_ERROR("Exception while processing"), - INVALID_TABLE("Table not found"), + INVALID_TABLE("Table not found", "42S02"), INVALID_COLUMN("Invalid Column Reference"), INVALID_TABLE_OR_COLUMN("Invalid Table Alias or Column Reference"), AMBIGUOUS_TABLE_OR_COLUMN("Ambiguous Table Alias or Column Reference"), @@ -39,7 +51,7 @@ INVALID_FUNCTION_SIGNATURE("Function Argument Type Mismatch"), INVALID_OPERATOR_SIGNATURE("Operator Argument Type Mismatch"), INVALID_ARGUMENT("Wrong Arguments"), - INVALID_ARGUMENT_LENGTH("Arguments Length Mismatch"), + INVALID_ARGUMENT_LENGTH("Arguments Length Mismatch", "21000"), INVALID_ARGUMENT_TYPE("Argument Type Mismatch"), INVALID_JOIN_CONDITION_1("Both Left and Right Aliases Encountered in Join"), INVALID_JOIN_CONDITION_2("Neither Left nor Right Aliases Encountered in Join"), @@ -87,8 +99,79 @@ NEED_PARTITION_ERROR("need to specify partition columns because the destination table is partitioned."); private String mesg; + private String SQLState; + + private static char SPACE = ' '; + private static Pattern ERROR_MESSAGE_PATTERN = Pattern.compile(".*line [0-9]+:[0-9]+ (.*)"); + private static Map mesgToErrorMsgMap = new HashMap(); + private static int minMesgLength = -1; + + static { + for (ErrorMsg errorMsg : values()) { + mesgToErrorMsgMap.put(errorMsg.getMsg().trim(), errorMsg); + + int length = errorMsg.getMsg().trim().length(); + if (minMesgLength == -1 || length < minMesgLength) + minMesgLength = length; + } + } + + /** + * For a given error message string, searches for a ErrorMsg + * enum that appears to be a match. If an match is found, returns the + * SQLState associated with the ErrorMsg. If a match + * is not found or ErrorMsg has no SQLState, returns + * the SQLState bound to the GENERIC_ERROR + * ErrorMsg. + * + * @param mesg An error message string + * @return SQLState + */ + public static String findSQLState(String mesg) { + + //first see if there is a direct match + ErrorMsg errorMsg = mesgToErrorMsgMap.get(mesg); + if (errorMsg != null) { + if (errorMsg.getSQLState() != null) + return errorMsg.getSQLState(); + else + return GENERIC_ERROR.getSQLState(); + } + + //if not see if the mesg follows type of format, which is typically the case: + //line 1:14 Table not found table_name + String truncatedMesg = mesg.trim(); + Matcher match = ERROR_MESSAGE_PATTERN.matcher(mesg); + if (match.matches()) truncatedMesg = match.group(1); + + //appends might exist after the root message, so strip tokens off until we match + while (truncatedMesg.length() > minMesgLength) { + errorMsg = mesgToErrorMsgMap.get(truncatedMesg.trim()); + if (errorMsg != null) { + if (errorMsg.getSQLState() != null) + return errorMsg.getSQLState(); + else + return GENERIC_ERROR.getSQLState(); + } + + int lastSpace = truncatedMesg.lastIndexOf(SPACE); + if (lastSpace == -1) break; + + // hack off the last word and try again + truncatedMesg = truncatedMesg.substring(0, lastSpace).trim(); + } + + return GENERIC_ERROR.getSQLState(); + } + ErrorMsg(String mesg) { + //42000 is the generic SQLState for syntax error. + this(mesg, "42000"); + } + + ErrorMsg(String mesg, String SQLState) { this.mesg = mesg; + this.SQLState = SQLState; } private int getLine(ASTNode tree) { @@ -140,4 +223,7 @@ return mesg; } + public String getSQLState() { + return SQLState; -} + } +} Index: build.properties =================================================================== --- build.properties (revision 808570) +++ build.properties Sun Aug 23 00:08:19 PDT 2009 @@ -3,7 +3,7 @@ version=0.5.0 year=2009 -hadoop.version=0.19.0 +hadoop.version=0.18.3 hadoop.mirror=http://archive.apache.org/dist build.dir.hive=${hive.root}/build Index: service/src/java/org/apache/hadoop/hive/service/HiveServer.java =================================================================== --- service/src/java/org/apache/hadoop/hive/service/HiveServer.java (revision 807721) +++ service/src/java/org/apache/hadoop/hive/service/HiveServer.java Tue Aug 25 16:56:49 PDT 2009 @@ -92,7 +92,7 @@ /** * Executes a query. * - * @param query HiveQL query to execute + * @param cmd HiveQL query to execute */ public void execute(String cmd) throws HiveServerException, TException { HiveServerHandler.LOG.info("Running the query: " + cmd); @@ -103,11 +103,17 @@ String cmd_1 = cmd_trimmed.substring(tokens[0].length()).trim(); int ret = 0; + String errorMessage = ""; + String SQLState = null; + try { CommandProcessor proc = CommandProcessorFactory.get(tokens[0]); if(proc != null) { if (proc instanceof Driver) { - ret = driver.run(cmd); + Driver.DriverResponse response = driver.runCommand(cmd); + ret = response.getResponseCode(); + SQLState = response.getSQLState(); + errorMessage = response.getErrorMessage(); } else { ret = proc.run(cmd_1); } @@ -117,7 +123,8 @@ } if (ret != 0) { - throw new HiveServerException("Query returned non-zero code: " + ret); + throw new HiveServerException("Query returned non-zero code: " + ret + + ", cause: " + errorMessage, ret, SQLState); } } @@ -317,9 +324,15 @@ public static void main(String[] args) { try { int port = 10000; + for(String arg: args) System.out.println("arg: " + arg); if (args.length >= 1) { + try { - port = Integer.parseInt(args[0]); - } + port = Integer.parseInt(args[0]); + } + catch(NumberFormatException e) { + + } + } TServerTransport serverTransport = new TServerSocket(port); ThriftHiveProcessorFactory hfactory = new ThriftHiveProcessorFactory(null); TThreadPoolServer.Options options = new TThreadPoolServer.Options();