diff --git ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java index fe929fc..3ac97ae 100644 --- ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java +++ ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java @@ -23,7 +23,6 @@ import java.io.OutputStream; import java.io.PrintStream; import java.io.Serializable; -import java.lang.annotation.Annotation; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; @@ -65,6 +64,14 @@ private Set> visitedOps = new HashSet>(); private boolean isLogical = false; + private static String[] INDENTS = new String[10]; + + static { + for (int i = 0; i < INDENTS.length; i++) { + INDENTS[i] = newIndentString((i + 1) << 1); + } + } + public ExplainTask() { super(); } @@ -137,7 +144,7 @@ public JSONObject getJSONLogicalPlan(PrintStream out, ExplainWork work) throws E if (work.getParseContext() != null) { out.print("LOGICAL PLAN:"); - JSONObject jsonPlan = outputMap(work.getParseContext().getTopOps(), true, + JSONObject jsonPlan = outputMap(work.getParseContext().getTopOps(), out, jsonOutput, work.getExtended(), 0); if (out != null) { out.println(); @@ -243,23 +250,27 @@ public int execute(DriverContext driverContext) { } private String indentString(int indent) { + if (indent % 2 == 0 && ((indent >> 1) - 1 < INDENTS.length)) { + return INDENTS[(indent >> 1) - 1]; + } + return newIndentString(indent); + } + + private static String newIndentString(int indent) { StringBuilder sb = new StringBuilder(); for (int i = 0; i < indent; ++i) { - sb.append(" "); + sb.append(' '); } - return sb.toString(); } - private JSONObject outputMap(Map mp, boolean hasHeader, PrintStream out, + private JSONObject outputMap(Map mp, PrintStream out, boolean extended, boolean jsonOutput, int indent) throws Exception { TreeMap tree = new TreeMap(); tree.putAll(mp); JSONObject json = jsonOutput ? new JSONObject() : null; - if (out != null && hasHeader && !mp.isEmpty()) { - out.println(); - } + for (Entry ent : tree.entrySet()) { // Print the key if (out != null) { @@ -369,7 +380,7 @@ else if (o instanceof Serializable) { out.println(); } JSONObject jsonOut = outputPlan((Serializable) o, out, extended, - jsonOutput, jsonOutput ? 0 : (hasHeader ? indent + 2 : indent)); + jsonOutput, indent); if (jsonOutput) { outputArray.put(jsonOut); } @@ -407,25 +418,24 @@ private JSONObject outputPlan(Serializable work, private JSONObject outputPlan(Serializable work, PrintStream out, boolean extended, boolean jsonOutput, int indent, String appendToHeader) throws Exception { // Check if work has an explain annotation - Annotation note = work.getClass().getAnnotation(Explain.class); - - String keyJSONObject = null; + Explain pnote = work.getClass().getAnnotation(Explain.class); + String pheader = null; - if (note instanceof Explain) { - Explain xpl_note = (Explain) note; - if (extended || xpl_note.normalExplain()) { - keyJSONObject = xpl_note.displayName(); + if (pnote != null) { + if (extended || pnote.normalExplain()) { + pheader = pnote.displayName(); if (out != null) { out.print(indentString(indent)); if (appendToHeader != null && !appendToHeader.isEmpty()) { - out.println(xpl_note.displayName() + appendToHeader); + out.println(pnote.displayName() + appendToHeader); } else { - out.println(xpl_note.displayName()); + out.println(pnote.displayName()); } } } } + int cindent = pheader == null ? indent : indent + 2; JSONObject json = jsonOutput ? new JSONObject() : null; // If this is an operator then we need to call the plan generation on the // conf and then the children @@ -435,29 +445,25 @@ private JSONObject outputPlan(Serializable work, PrintStream out, if (operator.getConf() != null) { String appender = isLogical ? " (" + operator.getOperatorId() + ")" : ""; JSONObject jsonOut = outputPlan(operator.getConf(), out, extended, - jsonOutput, jsonOutput ? 0 : indent, appender); + jsonOutput, cindent, appender); if (jsonOutput) { - json = jsonOut; + json = jsonOut; } } if (!visitedOps.contains(operator) || !isLogical) { visitedOps.add(operator); if (operator.getChildOperators() != null) { - int cindent = jsonOutput ? 0 : indent + 2; + int gindent = operator.getConf() == null ? cindent : cindent + 2; for (Operator op : operator.getChildOperators()) { - JSONObject jsonOut = outputPlan(op, out, extended, jsonOutput, cindent); + JSONObject jsonOut = outputPlan(op, out, extended, jsonOutput, gindent); if (jsonOutput) { ((JSONObject)json.get(JSONObject.getNames(json)[0])).accumulate("children", jsonOut); } } } } - - if (jsonOutput) { - return json; - } - return null; + return json; } // We look at all methods that generate values for explain @@ -465,140 +471,126 @@ private JSONObject outputPlan(Serializable work, PrintStream out, Arrays.sort(methods, new MethodComparator()); for (Method m : methods) { - int prop_indents = jsonOutput ? 0 : indent + 2; - note = m.getAnnotation(Explain.class); - - if (note instanceof Explain) { - Explain xpl_note = (Explain) note; + Explain cnote = m.getAnnotation(Explain.class); + if (cnote == null) { + continue; + } - if (extended || xpl_note.normalExplain()) { + if (extended || cnote.normalExplain()) { - Object val = null; - try { - val = m.invoke(work); - } - catch (InvocationTargetException ex) { - // Ignore the exception, this may be caused by external jars - val = null; - } + Object val; + try { + val = m.invoke(work); + } catch (InvocationTargetException ex) { + // Ignore the exception, this may be caused by external jars + val = null; + } - if (val == null) { - continue; - } + if (val == null) { + continue; + } - String header = null; - boolean skipHeader = xpl_note.skipHeader(); - boolean emptyHeader = false; + String cheader = null; + if (!cnote.skipHeader() && !cnote.displayName().isEmpty()) { + cheader = cnote.displayName() + ":"; + } - if (!xpl_note.displayName().equals("")) { - header = indentString(prop_indents) + xpl_note.displayName() + ":"; + // Try the output as a primitive object + if (isPrintable(val)) { + if (out != null && shouldPrint(cnote, val)) { + out.print(indentString(cindent)); + if (cheader != null) { + out.print(cheader); + out.print(' '); + } + out.println(val); } - else { - emptyHeader = true; - prop_indents = indent; - header = indentString(prop_indents); + if (jsonOutput && shouldPrint(cnote, val)) { + json.put(cheader, val.toString()); } + continue; + } - // Try the output as a primitive object - if (isPrintable(val)) { - if (out != null && shouldPrint(xpl_note, val)) { - if (!skipHeader) { - out.printf("%s ", header); - } - out.println(val); - } - if (jsonOutput && shouldPrint(xpl_note, val)) { - json.put(header, val.toString()); - } + // Try this as a map + if (val instanceof Map) { + // Go through the map and print out the stuff + Map mp = (Map) val; + if (mp.isEmpty()) { continue; } - - int ind = 0; - if (!jsonOutput) { - if (!skipHeader) { - ind = prop_indents + 2; - } else { - ind = indent; - } + if (jsonOutput && cheader == null) { + continue; } - // Try this as a map - try { - // Go through the map and print out the stuff - Map mp = (Map) val; + if (out != null && cheader != null) { + out.print(indentString(cindent)); + out.println(cheader); + } - if (out != null && !skipHeader && mp != null && !mp.isEmpty()) { - out.print(header); - } + int gindent = cheader != null ? cindent + 2 : cindent; + JSONObject jsonOut = outputMap(mp, out, extended, jsonOutput, gindent); + if (json != null && jsonOut != null) { + json.put(cheader, jsonOut); + } + continue; + } - JSONObject jsonOut = outputMap(mp, !skipHeader && !emptyHeader, out, extended, jsonOutput, ind); - if (jsonOutput && !mp.isEmpty()) { - json.put(header, jsonOut); - } + // Try this as a list + List l = null; + if (val instanceof List) { + l = (List) val; + } else if (val instanceof Set) { + l = new LinkedList((Set) val); + } + if (l != null) { + if (l.isEmpty()) { continue; } - catch (ClassCastException ce) { - // Ignore - all this means is that this is not a map + if (jsonOutput && cheader == null) { + continue; } - // Try this as a list - try { - List l; - - try { - l = (List) val; - } catch (ClassCastException e) { - Set s = (Set) val; - l = new LinkedList(); - l.addAll(s); - } - - if (out != null && !skipHeader && l != null && !l.isEmpty()) { - out.print(header); - } + if (out != null && cheader != null) { + out.print(indentString(cindent)); + out.print(cheader); + } - JSONArray jsonOut = outputList(l, out, !skipHeader && !emptyHeader, extended, jsonOutput, ind); + int gindent = cheader != null ? cindent + 2 : cindent; + JSONArray jsonOut = outputList(l, out, cheader != null, extended, jsonOutput, gindent); + if (json != null && jsonOut != null) { + json.put(cheader, jsonOut); + } + continue; + } - if (jsonOutput && !l.isEmpty()) { - json.put(header, jsonOut); - } + // Finally check if it is serializable + if (val instanceof Serializable) { + Serializable s = (Serializable) val; - continue; - } - catch (ClassCastException ce) { - // Ignore + if (out != null && cheader != null) { + out.print(indentString(cindent)); + out.println(cheader); } - // Finally check if it is serializable - try { - Serializable s = (Serializable) val; - - if (!skipHeader && out != null) { - out.println(header); - } - JSONObject jsonOut = outputPlan(s, out, extended, jsonOutput, ind); - if (jsonOutput) { - if (!skipHeader) { - json.put(header, jsonOut); - } else { - for(String k: JSONObject.getNames(jsonOut)) { - json.put(k, jsonOut.get(k)); - } + int gindent = cheader != null ? cindent + 2 : cindent; + JSONObject jsonOut = outputPlan(s, out, extended, jsonOutput, gindent); + if (jsonOutput) { + if (cheader != null) { + json.put(cheader, jsonOut); + } else { + for(String k: JSONObject.getNames(jsonOut)) { + json.put(k, jsonOut.get(k)); } } - continue; - } - catch (ClassCastException ce) { - // Ignore } } } } if (jsonOutput) { - if (keyJSONObject != null) { + if (pheader != null) { JSONObject ret = new JSONObject(); - ret.put(keyJSONObject, json); + ret.put(pheader, json); return ret; } @@ -652,7 +644,6 @@ private JSONObject outputDependencies(Task task, PrintStream out, JSONObject parentJson, boolean jsonOutput, boolean taskType, int indent) throws Exception { - boolean first = true; JSONObject json = jsonOutput ? new JSONObject() : null; if (out != null) { out.print(indentString(indent)); @@ -671,13 +662,11 @@ private JSONObject outputDependencies(Task task, } } else { - StringBuffer s = new StringBuffer(); - first = true; + StringBuilder s = new StringBuilder(); for (Task parent : task.getParentTasks()) { - if (!first) { + if (s.length() > 0) { s.append(", "); } - first = false; s.append(parent.getId()); } @@ -703,13 +692,11 @@ private JSONObject outputDependencies(Task task, if (task instanceof ConditionalTask && ((ConditionalTask) task).getListTasks() != null) { - StringBuffer s = new StringBuffer(); - first = true; + StringBuilder s = new StringBuilder(); for (Task con : ((ConditionalTask) task).getListTasks()) { - if (!first) { + if (s.length() > 0) { s.append(", "); } - first = false; s.append(con.getId()); } diff --git ql/src/test/results/clientpositive/auto_join0.q.out ql/src/test/results/clientpositive/auto_join0.q.out index 31f76ed..af3ee2c 100644 --- ql/src/test/results/clientpositive/auto_join0.q.out +++ ql/src/test/results/clientpositive/auto_join0.q.out @@ -56,36 +56,36 @@ STAGE PLANS: Stage: Stage-2 Map Reduce Map Operator Tree: - TableScan - alias: src - Statistics: Num rows: 29 Data size: 5812 Basic stats: COMPLETE Column stats: NONE - Filter Operator - predicate: (key < 10) (type: boolean) + TableScan + alias: src + Statistics: Num rows: 29 Data size: 5812 Basic stats: COMPLETE Column stats: NONE + Filter Operator + predicate: (key < 10) (type: boolean) + Statistics: Num rows: 9 Data size: 1803 Basic stats: COMPLETE Column stats: NONE + Select Operator + expressions: key (type: string), value (type: string) + outputColumnNames: _col0, _col1 Statistics: Num rows: 9 Data size: 1803 Basic stats: COMPLETE Column stats: NONE - Select Operator - expressions: key (type: string), value (type: string) - outputColumnNames: _col0, _col1 - Statistics: Num rows: 9 Data size: 1803 Basic stats: COMPLETE Column stats: NONE - Map Join Operator - condition map: - Inner Join 0 to 1 - condition expressions: - 0 {_col0} {_col1} - 1 {_col0} {_col1} - keys: - 0 - 1 + Map Join Operator + condition map: + Inner Join 0 to 1 + condition expressions: + 0 {_col0} {_col1} + 1 {_col0} {_col1} + keys: + 0 + 1 + outputColumnNames: _col0, _col1, _col2, _col3 + Statistics: Num rows: 9 Data size: 1983 Basic stats: COMPLETE Column stats: NONE + Select Operator + expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: string) outputColumnNames: _col0, _col1, _col2, _col3 Statistics: Num rows: 9 Data size: 1983 Basic stats: COMPLETE Column stats: NONE - Select Operator - expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: string) - outputColumnNames: _col0, _col1, _col2, _col3 + Reduce Output Operator + key expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: string) + sort order: ++++ Statistics: Num rows: 9 Data size: 1983 Basic stats: COMPLETE Column stats: NONE - Reduce Output Operator - key expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: string) - sort order: ++++ - Statistics: Num rows: 9 Data size: 1983 Basic stats: COMPLETE Column stats: NONE - value expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: string) + value expressions: _col0 (type: string), _col1 (type: string), _col2 (type: string), _col3 (type: string) Local Work: Map Reduce Local Work Reduce Operator Tree: @@ -103,18 +103,18 @@ STAGE PLANS: File Output Operator compressed: false table: - input format: org.apache.hadoop.mapred.SequenceFileInputFormat - output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat - serde: org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe + input format: org.apache.hadoop.mapred.SequenceFileInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveSequenceFileOutputFormat + serde: org.apache.hadoop.hive.serde2.lazybinary.LazyBinarySerDe Stage: Stage-3 Map Reduce Map Operator Tree: - TableScan - Reduce Output Operator - sort order: - Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONE - value expressions: _col0 (type: bigint) + TableScan + Reduce Output Operator + sort order: + Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONE + value expressions: _col0 (type: bigint) Reduce Operator Tree: Group By Operator aggregations: sum(VALUE._col0) @@ -129,9 +129,9 @@ STAGE PLANS: compressed: false Statistics: Num rows: 1 Data size: 8 Basic stats: COMPLETE Column stats: NONE table: - input format: org.apache.hadoop.mapred.TextInputFormat - output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat - serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe + input format: org.apache.hadoop.mapred.TextInputFormat + output format: org.apache.hadoop.hive.ql.io.HiveIgnoreKeyTextOutputFormat + serde: org.apache.hadoop.hive.serde2.lazy.LazySimpleSerDe Stage: Stage-0 Fetch Operator