You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by se...@apache.org on 2014/10/22 01:31:01 UTC
svn commit: r1633485 -
/hive/branches/branch-0.14/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
Author: sershe
Date: Tue Oct 21 23:31:00 2014
New Revision: 1633485
URL: http://svn.apache.org/r1633485
Log:
HIVE-8390 : CBO produces annoying exception message and wraps exceptions too much (Sergey Shelukhin, reviewed by Ashutosh Chauhan)
Modified:
hive/branches/branch-0.14/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
Modified: hive/branches/branch-0.14/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
URL: http://svn.apache.org/viewvc/hive/branches/branch-0.14/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java?rev=1633485&r1=1633484&r2=1633485&view=diff
==============================================================================
--- hive/branches/branch-0.14/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (original)
+++ hive/branches/branch-0.14/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java Tue Oct 21 23:31:00 2014
@@ -22,6 +22,9 @@ import static org.apache.hadoop.hive.con
import java.io.IOException;
import java.io.Serializable;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.UndeclaredThrowableException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Arrays;
@@ -9940,13 +9943,21 @@ public class SemanticAnalyzer extends Ba
* .getRowResolver(), true);
*/
} catch (Exception e) {
- LOG.error("CBO failed, skipping CBO. ", e);
- if (!conf.getBoolVar(ConfVars.HIVE_IN_TEST) ||
- (optiqPlanner.noColsMissingStats.get() > 0) ||
- e instanceof OptiqSemanticException) {
+ boolean isMissingStats = optiqPlanner.noColsMissingStats.get() > 0;
+ if (isMissingStats) {
+ LOG.error("CBO failed due to missing column stats (see previous errors), skipping CBO");
+ } else {
+ LOG.error("CBO failed, skipping CBO. ", e);
+ }
+ if (!conf.getBoolVar(ConfVars.HIVE_IN_TEST) || isMissingStats
+ || e instanceof OptiqSemanticException) {
reAnalyzeAST = true;
+ } else if (e instanceof SemanticException) {
+ throw (SemanticException)e;
+ } else if (e instanceof RuntimeException) {
+ throw (RuntimeException)e;
} else {
- throw e instanceof SemanticException ? (SemanticException) e : new SemanticException(e);
+ throw new SemanticException(e);
}
} finally {
runCBO = false;
@@ -12259,16 +12270,50 @@ public class SemanticAnalyzer extends Ba
optimizedOptiqPlan = Frameworks.withPlanner(this,
Frameworks.newConfigBuilder().typeSystem(new HiveTypeSystemImpl()).build());
} catch (Exception e) {
- if (semanticException != null)
- throw semanticException;
- else
- throw new RuntimeException(e);
+ rethrowCalciteException(e);
+ throw new AssertionError("rethrowCalciteException didn't throw for " + e.getMessage());
}
optiqOptimizedAST = ASTConverter.convert(optimizedOptiqPlan, topLevelFieldSchema);
return optiqOptimizedAST;
}
+ /*
+ * Unwraps a chain of useless UndeclaredThrowableException-s, InvocationTargetException-s
+ * and RuntimeException-s potentially coming from CBO/Calcite code.
+ */
+ private void rethrowCalciteException(Exception e) throws SemanticException {
+ Throwable first = (semanticException != null) ? semanticException : e,
+ current = first, cause = current.getCause();
+ while (cause != null) {
+ Throwable causeOfCause = cause.getCause();
+ if (current == first && causeOfCause == null && isUselessCause(first)) {
+ // "cause" is a root cause, and "e"/"first" is a useless exception it's wrapped in.
+ first = cause;
+ break;
+ } else if (causeOfCause != null && isUselessCause(cause)
+ && ExceptionHelper.resetCause(current, causeOfCause)) {
+ // "cause" was a useless intermediate cause and was replace it with its own cause.
+ cause = causeOfCause;
+ continue; // do loop once again with the new cause of "current"
+ }
+ current = cause;
+ cause = current.getCause();
+ }
+
+ if (first instanceof RuntimeException) {
+ throw (RuntimeException)first;
+ } else if (first instanceof SemanticException) {
+ throw (SemanticException)first;
+ }
+ throw new RuntimeException(first);
+ }
+
+ private boolean isUselessCause(Throwable t) {
+ return t instanceof RuntimeException || t instanceof InvocationTargetException
+ || t instanceof UndeclaredThrowableException;
+ }
+
@Override
public RelNode apply(RelOptCluster cluster, RelOptSchema relOptSchema, SchemaPlus rootSchema) {
RelNode optiqGenPlan = null;
@@ -14239,4 +14284,36 @@ public class SemanticAnalyzer extends Ba
return tabAliases;
}
}
+
+ private static class ExceptionHelper {
+ private static final Field CAUSE_FIELD = getField(Throwable.class, "cause"),
+ TARGET_FIELD = getField(InvocationTargetException.class, "target"),
+ MESSAGE_FIELD = getField(Throwable.class, "detailMessage");
+ private static Field getField(Class<?> clazz, String name) {
+ try {
+ Field f = clazz.getDeclaredField(name);
+ f.setAccessible(true);
+ return f;
+ } catch (Throwable t) {
+ return null;
+ }
+ }
+ public static boolean resetCause(Throwable target, Throwable newCause) {
+ try {
+ if (MESSAGE_FIELD == null) return false;
+ Field field = (target instanceof InvocationTargetException) ? TARGET_FIELD : CAUSE_FIELD;
+ if (field == null) return false;
+
+ Throwable oldCause = target.getCause();
+ String oldMsg = target.getMessage();
+ field.set(target, newCause);
+ if (oldMsg != null && oldMsg.equals(oldCause.toString())) {
+ MESSAGE_FIELD.set(target, newCause == null ? null : newCause.toString());
+ }
+ } catch (Throwable se) {
+ return false;
+ }
+ return true;
+ }
+ }
}