diff --git a/itests/util/src/main/java/org/apache/hadoop/hive/ql/QOutProcessor.java b/itests/util/src/main/java/org/apache/hadoop/hive/ql/QOutProcessor.java index b87d9045d0..cbce226fac 100644 --- a/itests/util/src/main/java/org/apache/hadoop/hive/ql/QOutProcessor.java +++ b/itests/util/src/main/java/org/apache/hadoop/hive/ql/QOutProcessor.java @@ -132,7 +132,8 @@ public String get() { "org\\.apache\\.hadoop\\.hive\\.metastore\\.model\\.MConstraint@([0-9]|[a-z])*", "^Repair: Added partition to metastore.*", "^latestOffsets.*", - "^minimumLag.*" + "^minimumLag.*", + ".*CBOPlan.*" }); public QOutProcessor(FsType fsType) { diff --git a/ql/src/java/org/apache/hadoop/hive/ql/Driver.java b/ql/src/java/org/apache/hadoop/hive/ql/Driver.java index 4f14fa59c1..3a20130820 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/Driver.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/Driver.java @@ -1047,7 +1047,7 @@ private String getExplainOutput(BaseSemanticAnalyzer sem, QueryPlan plan, if (conf.getBoolVar(ConfVars.HIVE_SERVER2_WEBUI_SHOW_GRAPH)) { JSONObject jsonPlan = task.getJSONPlan( null, rootTasks, sem.getFetchTask(), true, true, true, sem.getCboInfo(), - plan.getOptimizedQueryString()); + plan.getOptimizedCBOPlan(), plan.getOptimizedQueryString()); if (jsonPlan.getJSONObject(ExplainTask.STAGE_DEPENDENCIES) != null && jsonPlan.getJSONObject(ExplainTask.STAGE_DEPENDENCIES).length() <= conf.getIntVar(ConfVars.HIVE_SERVER2_WEBUI_MAX_GRAPH_SIZE)) { @@ -1057,7 +1057,7 @@ private String getExplainOutput(BaseSemanticAnalyzer sem, QueryPlan plan, } } else { task.getJSONPlan(ps, rootTasks, sem.getFetchTask(), false, true, true, sem.getCboInfo(), - plan.getOptimizedQueryString()); + plan.getOptimizedCBOPlan(), plan.getOptimizedQueryString()); ret = baos.toString(); } } catch (Exception e) { diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java b/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java index b9d1e0b93f..8223d6b823 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainTask.java @@ -237,12 +237,12 @@ public JSONObject getJSONPlan(PrintStream out, ExplainWork work) throws Exception { return getJSONPlan(out, work.getRootTasks(), work.getFetchTask(), work.isFormatted(), work.getExtended(), work.isAppendTaskType(), work.getCboInfo(), - work.getOptimizedSQL()); + work.getCboPlan(), work.getOptimizedSQL()); } public JSONObject getJSONPlan(PrintStream out, List> tasks, Task fetchTask, boolean jsonOutput, boolean isExtended, boolean appendTaskType, String cboInfo, - String optimizedSQL) throws Exception { + String cboPlan, String optimizedSQL) throws Exception { // If the user asked for a formatted output, dump the json output // in the output stream @@ -252,6 +252,15 @@ public JSONObject getJSONPlan(PrintStream out, List> tasks, Task fetc out = null; } + if (cboPlan != null) { + if (jsonOutput) { + outJSONObject.put("CBOPlan", cboPlan); + } else { + out.print("CBO PLAN:"); + out.println(cboPlan); + } + } + if (optimizedSQL != null) { if (jsonOutput) { outJSONObject.put("optimizedSQL", optimizedSQL); diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java index 20501cf75e..64474a37d1 100644 --- a/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java +++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/CalcitePlanner.java @@ -553,7 +553,10 @@ Operator genOPTree(ASTNode ast, PlannerContext plannerCtx) throws SemanticExcept // Do not include join cost this.ctx.setCalcitePlan(RelOptUtil.toString(newPlan)); } - } else if (explainConfig.isExtended() || explainConfig.isFormatted()) { + } else if (explainConfig.isFormatted()) { + this.ctx.setCalcitePlan(HiveRelOptUtil.toJsonString(newPlan)); + this.ctx.setOptimizedSql(getOptimizedSql(newPlan)); + } else if (explainConfig.isExtended()) { this.ctx.setOptimizedSql(getOptimizedSql(newPlan)); } } diff --git a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestExplainTask.java b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestExplainTask.java index a0c0413431..8ba612ebce 100644 --- a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestExplainTask.java +++ b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestExplainTask.java @@ -218,7 +218,7 @@ public void testGetJSONPlan() throws Exception { JsonNode result = objectMapper.readTree(uut.getJSONPlan(null, tasks, null, true, - false, false, "Plan Optimized by CBO", null).toString()); + false, false, "Plan Optimized by CBO", null, null).toString()); JsonNode expected = objectMapper.readTree("{\"cboInfo\":\"Plan Optimized by CBO\", \"STAGE DEPENDENCIES\":{\"mockTaskId\":" + "{\"ROOT STAGE\":\"TRUE\",\"BACKUP STAGE\":\"backup-id-mock\"}},\"STAGE PLANS\":" + "{\"mockTaskId\":{}}}"); diff --git a/ql/src/test/results/clientpositive/plan_json.q.out b/ql/src/test/results/clientpositive/plan_json.q.out index b16e574e3d..8dfd5fcfee 100644 --- a/ql/src/test/results/clientpositive/plan_json.q.out +++ b/ql/src/test/results/clientpositive/plan_json.q.out @@ -6,4 +6,3 @@ POSTHOOK: query: EXPLAIN FORMATTED SELECT count(1) FROM src POSTHOOK: type: QUERY POSTHOOK: Input: default@src #### A masked pattern was here #### -{"optimizedSQL":"SELECT COUNT(*) AS `$f0`\nFROM `default`.`src`","cboInfo":"Plan optimized by CBO.","STAGE DEPENDENCIES":{"Stage-0":{"ROOT STAGE":"TRUE"}},"STAGE PLANS":{"Stage-0":{"Fetch Operator":{"limit:":"1","Processor Tree:":{"ListSink":{"OperatorId:":"LIST_SINK_7"}}}}}}