You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hive.apache.org by ha...@apache.org on 2014/04/30 17:45:50 UTC

svn commit: r1591363 - in /hive/trunk/ql/src: java/org/apache/hadoop/hive/ql/exec/ java/org/apache/hadoop/hive/ql/parse/ java/org/apache/hadoop/hive/ql/plan/ test/queries/clientpositive/ test/results/clientpositive/

Author: hashutosh
Date: Wed Apr 30 15:45:49 2014
New Revision: 1591363

URL: http://svn.apache.org/r1591363
Log:
HIVE-6031 : explain subquery rewrite for where clause predicates (Harish Butani via Ashutosh Chauhan)

Added:
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainSQRewriteTask.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ExplainSQRewriteSemanticAnalyzer.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryDiagnostic.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/plan/ExplainSQRewriteWork.java
    hive/trunk/ql/src/test/queries/clientpositive/subquery_exists_explain_rewrite.q
    hive/trunk/ql/src/test/queries/clientpositive/subquery_in_explain_rewrite.q
    hive/trunk/ql/src/test/results/clientpositive/subquery_exists_explain_rewrite.q.out
    hive/trunk/ql/src/test/results/clientpositive/subquery_in_explain_rewrite.q.out
Modified:
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/TaskFactory.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QB.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java
    hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainSQRewriteTask.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainSQRewriteTask.java?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainSQRewriteTask.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/ExplainSQRewriteTask.java Wed Apr 30 15:45:49 2014
@@ -0,0 +1,206 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hive.ql.exec;
+
+import static org.apache.hadoop.hive.serde.serdeConstants.STRING_TYPE_NAME;
+
+import java.io.OutputStream;
+import java.io.PrintStream;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Set;
+
+import org.antlr.runtime.TokenRewriteStream;
+import org.apache.hadoop.fs.Path;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.ql.DriverContext;
+import org.apache.hadoop.hive.ql.parse.ASTNode;
+import org.apache.hadoop.hive.ql.parse.HiveParser;
+import org.apache.hadoop.hive.ql.parse.QB;
+import org.apache.hadoop.hive.ql.parse.QBSubQuery;
+import org.apache.hadoop.hive.ql.parse.SubQueryDiagnostic;
+import org.apache.hadoop.hive.ql.plan.ExplainSQRewriteWork;
+import org.apache.hadoop.hive.ql.plan.api.StageType;
+import org.apache.hadoop.io.IOUtils;
+import org.apache.hadoop.util.StringUtils;
+
+
+public class ExplainSQRewriteTask extends Task<ExplainSQRewriteWork> implements Serializable {
+  private static final long serialVersionUID = 1L;
+
+  @Override
+  public StageType getType() {
+    return StageType.EXPLAIN;
+  }
+  
+  @Override
+  public int execute(DriverContext driverContext) {
+
+    PrintStream out = null;
+    try {
+      Path resFile = new Path(work.getResFile());
+      OutputStream outS = resFile.getFileSystem(conf).create(resFile);
+      out = new PrintStream(outS);
+
+      QB qb = work.getQb();
+      TokenRewriteStream stream = work.getCtx().getTokenRewriteStream();
+      String program = "sq rewrite";
+      ASTNode ast = work.getAst();
+      
+      try {
+        addRewrites(stream, qb, program, out);
+        out.println("\nRewritten Query:\n" + stream.toString(program, 
+            ast.getTokenStartIndex(), ast.getTokenStopIndex()));
+      } finally {
+        stream.deleteProgram(program);
+      }
+      
+      out.close();
+      out = null;
+      return (0);
+    }
+    catch (Exception e) {
+      console.printError("Failed with exception " + e.getMessage(),
+          "\n" + StringUtils.stringifyException(e));
+      return (1);
+    }
+    finally {
+      IOUtils.closeStream(out);
+    }
+  }
+  
+  void addRewrites(TokenRewriteStream stream, QB qb, String program,
+      PrintStream out) {
+    QBSubQuery sqW = qb.getWhereClauseSubQueryPredicate();
+    QBSubQuery sqH = qb.getHavingClauseSubQueryPredicate();
+
+    if (sqW != null || sqH != null) {
+
+      ASTNode sqNode = sqW != null ? sqW.getOriginalSubQueryASTForRewrite()
+          : sqH.getOriginalSubQueryASTForRewrite();
+      ASTNode tokQry = getQueryASTNode(sqNode);
+      ASTNode tokFrom = (ASTNode) tokQry.getChild(0);
+
+      StringBuilder addedJoins = new StringBuilder();
+
+      if (sqW != null) {
+        addRewrites(stream, sqW, program, out, qb.getId(), true, addedJoins);
+      }
+
+      if (sqH != null) {
+        addRewrites(stream, sqH, program, out, qb.getId(), false, addedJoins);
+      }
+      stream.insertAfter(program, tokFrom.getTokenStopIndex(), addedJoins);
+    }
+    
+    Set<String> sqAliases = qb.getSubqAliases();
+    for(String sqAlias : sqAliases) {
+      addRewrites(stream, qb.getSubqForAlias(sqAlias).getQB(), program, out);
+    }
+  }
+  
+  void addRewrites(TokenRewriteStream stream, QBSubQuery sq, String program, 
+      PrintStream out, String qbAlias, boolean isWhere, StringBuilder addedJoins) {
+    ASTNode sqNode = sq.getOriginalSubQueryASTForRewrite();
+    ASTNode tokQry = getQueryASTNode(sqNode);
+    ASTNode tokInsert = (ASTNode) tokQry.getChild(1);
+    ASTNode tokWhere = null;
+    
+    for(int i=0; i < tokInsert.getChildCount(); i++) {
+      if ( tokInsert.getChild(i).getType() == HiveParser.TOK_WHERE) {
+        tokWhere = (ASTNode) tokInsert.getChild(i);
+        break;
+      }
+    }
+    
+    SubQueryDiagnostic.QBSubQueryRewrite diag = sq.getDiagnostic();
+      String sqStr = diag.getRewrittenQuery();
+      String joinCond = diag.getJoiningCondition();
+      
+      /*
+       * the SubQuery predicate has been hoisted as a Join. The SubQuery predicate is replaced
+       * by a 'true' predicate in the Outer QB's where/having clause.
+       */
+      stream.replace(program, sqNode.getTokenStartIndex(),
+          sqNode.getTokenStopIndex(),
+          "1 = 1");
+      
+      String sqJoin = " " + 
+          getJoinKeyWord(sq) + 
+          " " +
+          sqStr + 
+          " " +
+          joinCond;
+      addedJoins.append(" ").append(sqJoin);
+      
+      String postJoinCond = diag.getOuterQueryPostJoinCond();
+      if ( postJoinCond != null ) {
+        stream.insertAfter(program, tokWhere.getTokenStopIndex(), " and " + postJoinCond);
+      }
+      
+      String qualifier = isWhere ? "Where Clause " : "Having Clause ";
+      if ( qbAlias != null ) {
+        qualifier = qualifier + "for Query Block '" + qbAlias + "' ";
+      }
+      out.println(String.format("\n%s Rewritten SubQuery:\n%s", 
+          qualifier, diag.getRewrittenQuery()));
+      out.println(String.format("\n%s SubQuery Joining Condition:\n%s", 
+          qualifier, diag.getJoiningCondition()));
+  }
+  
+  private String getJoinKeyWord(QBSubQuery sq) {
+    switch (sq.getJoinType()) {
+    case LEFTOUTER:
+      return "left outer join";
+    case LEFTSEMI:
+      return "left semi join";
+    case RIGHTOUTER:
+      return "right outer join";
+    case FULLOUTER:
+      return "full outer join";
+    case INNER:
+    default:
+      return "inner join";
+    }
+  }
+  
+  private ASTNode getQueryASTNode(ASTNode node) {
+    while( node != null && node.getType() != HiveParser.TOK_QUERY ) {
+      node = (ASTNode) node.getParent();
+    }
+    return node;
+  }
+
+  @Override
+  public String getName() {
+    return "EXPLAIN REWRITE";
+  }
+
+  @Override
+  public List<FieldSchema> getResultSchema() {
+    FieldSchema tmpFieldSchema = new FieldSchema();
+    List<FieldSchema> colList = new ArrayList<FieldSchema>();
+
+    tmpFieldSchema.setName(ExplainTask.EXPL_COLUMN_NAME);
+    tmpFieldSchema.setType(STRING_TYPE_NAME);
+
+    colList.add(tmpFieldSchema);
+    return colList;
+  }
+}

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/TaskFactory.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/TaskFactory.java?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/TaskFactory.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/exec/TaskFactory.java Wed Apr 30 15:45:49 2014
@@ -37,6 +37,7 @@ import org.apache.hadoop.hive.ql.plan.Co
 import org.apache.hadoop.hive.ql.plan.CopyWork;
 import org.apache.hadoop.hive.ql.plan.DDLWork;
 import org.apache.hadoop.hive.ql.plan.DependencyCollectionWork;
+import org.apache.hadoop.hive.ql.plan.ExplainSQRewriteWork;
 import org.apache.hadoop.hive.ql.plan.ExplainWork;
 import org.apache.hadoop.hive.ql.plan.FetchWork;
 import org.apache.hadoop.hive.ql.plan.FunctionWork;
@@ -78,6 +79,8 @@ public final class TaskFactory {
         FunctionTask.class));
     taskvec
         .add(new TaskTuple<ExplainWork>(ExplainWork.class, ExplainTask.class));
+    taskvec
+        .add(new TaskTuple<ExplainSQRewriteWork>(ExplainSQRewriteWork.class, ExplainSQRewriteTask.class));
     taskvec.add(new TaskTuple<ConditionalWork>(ConditionalWork.class,
         ConditionalTask.class));
     taskvec.add(new TaskTuple<MapredWork>(MapredWork.class,

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ExplainSQRewriteSemanticAnalyzer.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ExplainSQRewriteSemanticAnalyzer.java?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ExplainSQRewriteSemanticAnalyzer.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/ExplainSQRewriteSemanticAnalyzer.java Wed Apr 30 15:45:49 2014
@@ -0,0 +1,68 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+ package org.apache.hadoop.hive.ql.parse;
+
+import java.io.Serializable;
+import java.util.List;
+
+import org.apache.hadoop.hive.conf.HiveConf;
+import org.apache.hadoop.hive.metastore.api.FieldSchema;
+import org.apache.hadoop.hive.ql.exec.Task;
+import org.apache.hadoop.hive.ql.exec.TaskFactory;
+import org.apache.hadoop.hive.ql.plan.ExplainSQRewriteWork;
+
+public class ExplainSQRewriteSemanticAnalyzer extends BaseSemanticAnalyzer {
+  List<FieldSchema> fieldList;
+
+  public ExplainSQRewriteSemanticAnalyzer(HiveConf conf) throws SemanticException {
+    super(conf);
+  }
+
+  @SuppressWarnings("unchecked")
+  @Override
+  public void analyzeInternal(ASTNode ast) throws SemanticException {
+
+
+    ctx.setExplain(true);
+
+    // Create a semantic analyzer for the query
+    ASTNode input = (ASTNode) ast.getChild(0);
+    SemanticAnalyzer sem = (SemanticAnalyzer)
+        SemanticAnalyzerFactory.get(conf, input);
+    sem.analyze(input, ctx);
+    sem.validate();
+
+    ctx.setResFile(ctx.getLocalTmpPath());
+
+    ExplainSQRewriteWork work = new ExplainSQRewriteWork(ctx.getResFile().toString(),
+        sem.getQB(),
+        input,
+        ctx
+        );
+
+    Task<? extends Serializable> explTask = TaskFactory.get(work, conf);
+
+    fieldList = explTask.getResultSchema();
+    rootTasks.add(explTask);
+  }
+
+  @Override
+  public List<FieldSchema> getResultSchema() {
+    return fieldList;
+  }
+}

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveLexer.g Wed Apr 30 15:45:49 2014
@@ -294,6 +294,7 @@ KW_PRINCIPALS: 'PRINCIPALS';
 KW_COMPACT: 'COMPACT';
 KW_COMPACTIONS: 'COMPACTIONS';
 KW_TRANSACTIONS: 'TRANSACTIONS';
+KW_REWRITE : 'REWRITE';
 
 // Operators
 // NOTE: if you add a new function/operator, add it to sysFuncNames so that describe function _FUNC_ will work.

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/HiveParser.g Wed Apr 30 15:45:49 2014
@@ -226,6 +226,7 @@ TOK_ALTERVIEW_DROPPARTS;
 TOK_ALTERVIEW_RENAME;
 TOK_VIEWPARTCOLS;
 TOK_EXPLAIN;
+TOK_EXPLAIN_SQ_REWRITE;
 TOK_TABLESERIALIZER;
 TOK_TABLEPROPERTIES;
 TOK_TABLEPROPLIST;
@@ -467,6 +468,8 @@ import java.util.HashMap;
     xlateMap.put("KW_VALUE_TYPE", "\$VALUE\$");
     xlateMap.put("KW_ELEM_TYPE", "\$ELEM\$");
     xlateMap.put("KW_DEFINED", "DEFINED");
+    xlateMap.put("KW_SUBQUERY", "SUBQUERY");
+    xlateMap.put("KW_REWRITE", "REWRITE");
 
     // Operators
     xlateMap.put("DOT", ".");
@@ -616,8 +619,11 @@ statement
 explainStatement
 @init { pushMsg("explain statement", state); }
 @after { popMsg(state); }
-	: KW_EXPLAIN (explainOptions=KW_EXTENDED|explainOptions=KW_FORMATTED|explainOptions=KW_DEPENDENCY|explainOptions=KW_LOGICAL)? execStatement
-      -> ^(TOK_EXPLAIN execStatement $explainOptions?)
+	: KW_EXPLAIN 
+	  ( (explainOptions=KW_EXTENDED|explainOptions=KW_FORMATTED|explainOptions=KW_DEPENDENCY|explainOptions=KW_LOGICAL)? execStatement
+          -> ^(TOK_EXPLAIN execStatement $explainOptions?) |
+      KW_REWRITE queryStatementExpression[true] -> ^(TOK_EXPLAIN_SQ_REWRITE queryStatementExpression)
+    )
 	;
 
 execStatement

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/IdentifiersParser.g Wed Apr 30 15:45:49 2014
@@ -538,5 +538,5 @@ functionIdentifier
 
 nonReserved
     :
-    KW_TRUE | KW_FALSE | KW_LIKE | KW_EXISTS | KW_ASC | KW_DESC | KW_ORDER | KW_GROUP | KW_BY | KW_AS | KW_INSERT | KW_OVERWRITE | KW_OUTER | KW_LEFT | KW_RIGHT | KW_FULL | KW_PARTITION | KW_PARTITIONS | KW_TABLE | KW_TABLES | KW_COLUMNS | KW_INDEX | KW_INDEXES | KW_REBUILD | KW_FUNCTIONS | KW_SHOW | KW_MSCK | KW_REPAIR | KW_DIRECTORY | KW_LOCAL | KW_USING | KW_CLUSTER | KW_DISTRIBUTE | KW_SORT | KW_UNION | KW_LOAD | KW_EXPORT | KW_IMPORT | KW_DATA | KW_INPATH | KW_IS | KW_NULL | KW_CREATE | KW_EXTERNAL | KW_ALTER | KW_CHANGE | KW_FIRST | KW_AFTER | KW_DESCRIBE | KW_DROP | KW_RENAME | KW_IGNORE | KW_PROTECTION | KW_TO | KW_COMMENT | KW_BOOLEAN | KW_TINYINT | KW_SMALLINT | KW_INT | KW_BIGINT | KW_FLOAT | KW_DOUBLE | KW_DATE | KW_DATETIME | KW_TIMESTAMP | KW_DECIMAL | KW_STRING | KW_ARRAY | KW_STRUCT | KW_UNIONTYPE | KW_PARTITIONED | KW_CLUSTERED | KW_SORTED | KW_INTO | KW_BUCKETS | KW_ROW | KW_ROWS | KW_FORMAT | KW_DELIMITED | KW_FIELDS | KW_TERMINATED | KW_ESCAPED | KW_COLLECTION | 
 KW_ITEMS | KW_KEYS | KW_KEY_TYPE | KW_LINES | KW_STORED | KW_FILEFORMAT | KW_SEQUENCEFILE | KW_TEXTFILE | KW_RCFILE | KW_ORCFILE | KW_PARQUETFILE | KW_INPUTFORMAT | KW_OUTPUTFORMAT | KW_INPUTDRIVER | KW_OUTPUTDRIVER | KW_OFFLINE | KW_ENABLE | KW_DISABLE | KW_READONLY | KW_NO_DROP | KW_LOCATION | KW_BUCKET | KW_OUT | KW_OF | KW_PERCENT | KW_ADD | KW_REPLACE | KW_RLIKE | KW_REGEXP | KW_TEMPORARY | KW_EXPLAIN | KW_FORMATTED | KW_PRETTY | KW_DEPENDENCY | KW_LOGICAL | KW_SERDE | KW_WITH | KW_DEFERRED | KW_SERDEPROPERTIES | KW_DBPROPERTIES | KW_LIMIT | KW_SET | KW_UNSET | KW_TBLPROPERTIES | KW_IDXPROPERTIES | KW_VALUE_TYPE | KW_ELEM_TYPE | KW_MAPJOIN | KW_STREAMTABLE | KW_HOLD_DDLTIME | KW_CLUSTERSTATUS | KW_UTC | KW_UTCTIMESTAMP | KW_LONG | KW_DELETE | KW_PLUS | KW_MINUS | KW_FETCH | KW_INTERSECT | KW_VIEW | KW_IN | KW_DATABASES | KW_MATERIALIZED | KW_SCHEMA | KW_SCHEMAS | KW_GRANT | KW_REVOKE | KW_SSL | KW_UNDO | KW_LOCK | KW_LOCKS | KW_UNLOCK | KW_SHARED | KW_EXCLUSIVE | KW_PROCEDURE |
  KW_UNSIGNED | KW_WHILE | KW_READ | KW_READS | KW_PURGE | KW_RANGE | KW_ANALYZE | KW_BEFORE | KW_BETWEEN | KW_BOTH | KW_BINARY | KW_CONTINUE | KW_CURSOR | KW_TRIGGER | KW_RECORDREADER | KW_RECORDWRITER | KW_SEMI | KW_LATERAL | KW_TOUCH | KW_ARCHIVE | KW_UNARCHIVE | KW_COMPUTE | KW_STATISTICS | KW_USE | KW_OPTION | KW_CONCATENATE | KW_SHOW_DATABASE | KW_UPDATE | KW_RESTRICT | KW_CASCADE | KW_SKEWED | KW_ROLLUP | KW_CUBE | KW_DIRECTORIES | KW_FOR | KW_GROUPING | KW_SETS | KW_TRUNCATE | KW_NOSCAN | KW_USER | KW_ROLE | KW_ROLES | KW_INNER | KW_DEFINED | KW_ADMIN | KW_JAR | KW_FILE | KW_OWNER | KW_PRINCIPALS | KW_ALL | KW_DEFAULT | KW_NONE | KW_COMPACT | KW_COMPACTIONS | KW_TRANSACTIONS
+    KW_TRUE | KW_FALSE | KW_LIKE | KW_EXISTS | KW_ASC | KW_DESC | KW_ORDER | KW_GROUP | KW_BY | KW_AS | KW_INSERT | KW_OVERWRITE | KW_OUTER | KW_LEFT | KW_RIGHT | KW_FULL | KW_PARTITION | KW_PARTITIONS | KW_TABLE | KW_TABLES | KW_COLUMNS | KW_INDEX | KW_INDEXES | KW_REBUILD | KW_FUNCTIONS | KW_SHOW | KW_MSCK | KW_REPAIR | KW_DIRECTORY | KW_LOCAL | KW_USING | KW_CLUSTER | KW_DISTRIBUTE | KW_SORT | KW_UNION | KW_LOAD | KW_EXPORT | KW_IMPORT | KW_DATA | KW_INPATH | KW_IS | KW_NULL | KW_CREATE | KW_EXTERNAL | KW_ALTER | KW_CHANGE | KW_FIRST | KW_AFTER | KW_DESCRIBE | KW_DROP | KW_RENAME | KW_IGNORE | KW_PROTECTION | KW_TO | KW_COMMENT | KW_BOOLEAN | KW_TINYINT | KW_SMALLINT | KW_INT | KW_BIGINT | KW_FLOAT | KW_DOUBLE | KW_DATE | KW_DATETIME | KW_TIMESTAMP | KW_DECIMAL | KW_STRING | KW_ARRAY | KW_STRUCT | KW_UNIONTYPE | KW_PARTITIONED | KW_CLUSTERED | KW_SORTED | KW_INTO | KW_BUCKETS | KW_ROW | KW_ROWS | KW_FORMAT | KW_DELIMITED | KW_FIELDS | KW_TERMINATED | KW_ESCAPED | KW_COLLECTION | 
 KW_ITEMS | KW_KEYS | KW_KEY_TYPE | KW_LINES | KW_STORED | KW_FILEFORMAT | KW_SEQUENCEFILE | KW_TEXTFILE | KW_RCFILE | KW_ORCFILE | KW_PARQUETFILE | KW_INPUTFORMAT | KW_OUTPUTFORMAT | KW_INPUTDRIVER | KW_OUTPUTDRIVER | KW_OFFLINE | KW_ENABLE | KW_DISABLE | KW_READONLY | KW_NO_DROP | KW_LOCATION | KW_BUCKET | KW_OUT | KW_OF | KW_PERCENT | KW_ADD | KW_REPLACE | KW_RLIKE | KW_REGEXP | KW_TEMPORARY | KW_EXPLAIN | KW_FORMATTED | KW_PRETTY | KW_DEPENDENCY | KW_LOGICAL | KW_SERDE | KW_WITH | KW_DEFERRED | KW_SERDEPROPERTIES | KW_DBPROPERTIES | KW_LIMIT | KW_SET | KW_UNSET | KW_TBLPROPERTIES | KW_IDXPROPERTIES | KW_VALUE_TYPE | KW_ELEM_TYPE | KW_MAPJOIN | KW_STREAMTABLE | KW_HOLD_DDLTIME | KW_CLUSTERSTATUS | KW_UTC | KW_UTCTIMESTAMP | KW_LONG | KW_DELETE | KW_PLUS | KW_MINUS | KW_FETCH | KW_INTERSECT | KW_VIEW | KW_IN | KW_DATABASES | KW_MATERIALIZED | KW_SCHEMA | KW_SCHEMAS | KW_GRANT | KW_REVOKE | KW_SSL | KW_UNDO | KW_LOCK | KW_LOCKS | KW_UNLOCK | KW_SHARED | KW_EXCLUSIVE | KW_PROCEDURE |
  KW_UNSIGNED | KW_WHILE | KW_READ | KW_READS | KW_PURGE | KW_RANGE | KW_ANALYZE | KW_BEFORE | KW_BETWEEN | KW_BOTH | KW_BINARY | KW_CONTINUE | KW_CURSOR | KW_TRIGGER | KW_RECORDREADER | KW_RECORDWRITER | KW_SEMI | KW_LATERAL | KW_TOUCH | KW_ARCHIVE | KW_UNARCHIVE | KW_COMPUTE | KW_STATISTICS | KW_USE | KW_OPTION | KW_CONCATENATE | KW_SHOW_DATABASE | KW_UPDATE | KW_RESTRICT | KW_CASCADE | KW_SKEWED | KW_ROLLUP | KW_CUBE | KW_DIRECTORIES | KW_FOR | KW_GROUPING | KW_SETS | KW_TRUNCATE | KW_NOSCAN | KW_USER | KW_ROLE | KW_ROLES | KW_INNER | KW_DEFINED | KW_ADMIN | KW_JAR | KW_FILE | KW_OWNER | KW_PRINCIPALS | KW_ALL | KW_DEFAULT | KW_NONE | KW_COMPACT | KW_COMPACTIONS | KW_TRANSACTIONS | KW_REWRITE
     ;

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QB.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QB.java?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QB.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QB.java Wed Apr 30 15:45:49 2014
@@ -76,7 +76,16 @@ public class QB {
 	 * clause.
 	 */
 	private int numSubQueryPredicates;
-  
+	
+	/*
+	 * for now a top level QB can have 1 where clause SQ predicate.
+	 */
+	private QBSubQuery whereClauseSubQueryPredicate;
+	
+  /*
+   * for now a top level QB can have 1 where clause SQ predicate.
+   */
+	private QBSubQuery havingClauseSubQueryPredicate;
 
   // results
 
@@ -340,5 +349,21 @@ public class QB {
 	protected int incrNumSubQueryPredicates() {
 		return ++numSubQueryPredicates;
 	}
+	
+	void setWhereClauseSubQueryPredicate(QBSubQuery sq) {
+	  whereClauseSubQueryPredicate = sq;
+  }
+	
+	public QBSubQuery getWhereClauseSubQueryPredicate() {
+	  return whereClauseSubQueryPredicate;
+	}
+	
+	void setHavingClauseSubQueryPredicate(QBSubQuery sq) {
+    havingClauseSubQueryPredicate = sq;
+  }
+	
+	public QBSubQuery getHavingClauseSubQueryPredicate() {
+    return havingClauseSubQueryPredicate;
+  }
 
 }

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/QBSubQuery.java Wed Apr 30 15:45:49 2014
@@ -35,6 +35,7 @@ import org.apache.hadoop.hive.ql.plan.Ex
 import org.apache.hadoop.hive.ql.plan.ExprNodeConstantDesc;
 import org.apache.hadoop.hive.ql.plan.ExprNodeDesc;
 import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
+import org.apache.hadoop.hive.ql.parse.SubQueryDiagnostic.QBSubQueryRewrite;
 
 public class QBSubQuery implements ISubQueryJoinInfo {
   
@@ -458,6 +459,8 @@ public class QBSubQuery implements ISubQ
   private int numOuterCorrExprsForHaving;
   
   private NotInCheck notInCheck;
+  
+  private QBSubQueryRewrite subQueryDiagnostic;
 
   public QBSubQuery(String outerQueryId,
       int sqIdx,
@@ -484,6 +487,8 @@ public class QBSubQuery implements ISubQ
     if ( operator.getType() == SubQueryType.NOT_IN ) {
       notInCheck = new NotInCheck();
     }
+    
+    subQueryDiagnostic = SubQueryDiagnostic.getRewrite(this, ctx.getTokenRewriteStream(), ctx);
   }
 
   public ASTNode getSubQueryAST() {
@@ -495,6 +500,13 @@ public class QBSubQuery implements ISubQ
   public SubQueryTypeDef getOperator() {
     return operator;
   }
+  
+  public ASTNode getOriginalSubQueryASTForRewrite() {
+    return (operator.getType() == SubQueryType.NOT_EXISTS
+        || operator.getType() == SubQueryType.NOT_IN ? 
+        (ASTNode) originalSQASTOrigin.getUsageNode().getParent() : 
+        originalSQASTOrigin.getUsageNode());
+  }
 
   void validateAndRewriteAST(RowResolver outerQueryRR,
 		  boolean forHavingClause,
@@ -650,6 +662,7 @@ public class QBSubQuery implements ISubQ
         rewriteCorrConjunctForHaving(parentQueryJoinCond, true, 
             outerQueryAlias, outerQueryRR, outerQueryCol);
       }
+      subQueryDiagnostic.addJoinCondition(parentQueryJoinCond, outerQueryCol != null, true);
     }
     joinConditionAST = SubQueryUtils.andAST(parentQueryJoinCond, joinConditionAST);
     setJoinType();
@@ -669,7 +682,11 @@ public class QBSubQuery implements ISubQ
   ASTNode updateOuterQueryFilter(ASTNode outerQryFilter) {
     if (postJoinConditionAST == null ) {
       return outerQryFilter;
-    } else if ( outerQryFilter == null ) {
+    }  
+    
+    subQueryDiagnostic.addPostJoinCondition(postJoinConditionAST);
+    
+    if ( outerQryFilter == null ) {
       return postJoinConditionAST;
     }
     ASTNode node = SubQueryUtils.andAST(outerQryFilter, postJoinConditionAST);
@@ -781,9 +798,13 @@ public class QBSubQuery implements ISubQ
         String exprAlias = getNextCorrExprAlias();
         ASTNode sqExprAlias = SubQueryUtils.createAliasAST(exprAlias);
         ASTNode sqExprForCorr = SubQueryUtils.createColRefAST(alias, exprAlias);
+        boolean corrCondLeftIsRewritten = false;
+        boolean corrCondRightIsRewritten = false;
 
         if ( conjunct.getLeftExprType().refersSubQuery() ) {
+          corrCondLeftIsRewritten = true;
           if ( forHavingClause && conjunct.getRightOuterColInfo() != null ) {
+            corrCondRightIsRewritten = true;
             rewriteCorrConjunctForHaving(conjunctAST, false, outerQueryAlias, 
                 parentQueryRR, conjunct.getRightOuterColInfo());
           }
@@ -793,16 +814,21 @@ public class QBSubQuery implements ISubQ
           subQueryJoinAliasExprs.add(sqExprForCorr);
           ASTNode selExpr = SubQueryUtils.createSelectItem(conjunct.getLeftExpr(), sqExprAlias);
           selectClause.addChild(selExpr);
+          subQueryDiagnostic.addSelectClauseRewrite(conjunct.getLeftExpr(), exprAlias);
           numOfCorrelationExprsAddedToSQSelect++;
           if ( containsAggregationExprs ) {
             ASTNode gBy = getSubQueryGroupByAST();
             SubQueryUtils.addGroupExpressionToFront(gBy, conjunct.getLeftExpr());
+            subQueryDiagnostic.addGByClauseRewrite(conjunct.getLeftExpr());
           }
           if ( notInCheck != null ) {
             notInCheck.addCorrExpr((ASTNode)conjunctAST.getChild(0));
           }
+          subQueryDiagnostic.addJoinCondition(conjunctAST, corrCondLeftIsRewritten, corrCondRightIsRewritten);
         } else {
+          corrCondRightIsRewritten = true;
           if ( forHavingClause && conjunct.getLeftOuterColInfo() != null ) {
+            corrCondLeftIsRewritten = true;
             rewriteCorrConjunctForHaving(conjunctAST, true, outerQueryAlias, 
                 parentQueryRR, conjunct.getLeftOuterColInfo());
           }
@@ -812,17 +838,21 @@ public class QBSubQuery implements ISubQ
           subQueryJoinAliasExprs.add(sqExprForCorr);
           ASTNode selExpr = SubQueryUtils.createSelectItem(conjunct.getRightExpr(), sqExprAlias);
           selectClause.addChild(selExpr);
+          subQueryDiagnostic.addSelectClauseRewrite(conjunct.getRightExpr(), exprAlias);
           numOfCorrelationExprsAddedToSQSelect++;
           if ( containsAggregationExprs ) {
             ASTNode gBy = getSubQueryGroupByAST();
             SubQueryUtils.addGroupExpressionToFront(gBy, conjunct.getRightExpr());
+            subQueryDiagnostic.addGByClauseRewrite(conjunct.getRightExpr());
           }
           if ( notInCheck != null ) {
             notInCheck.addCorrExpr((ASTNode)conjunctAST.getChild(1));
           }
+          subQueryDiagnostic.addJoinCondition(conjunctAST, corrCondLeftIsRewritten, corrCondRightIsRewritten);
         }
       } else {
         sqNewSearchCond = SubQueryUtils.andAST(sqNewSearchCond, conjunctAST);
+        subQueryDiagnostic.addWhereClauseRewrite(conjunctAST);
       }
     }
 
@@ -834,6 +864,7 @@ public class QBSubQuery implements ISubQ
          * left.
          */
         sqNewSearchCond = SubQueryUtils.constructTrueCond();
+        subQueryDiagnostic.addWhereClauseRewrite("1 = 1");
       }
       whereClause.setChild(0, sqNewSearchCond);
     }
@@ -870,6 +901,8 @@ public class QBSubQuery implements ISubQ
     for(ASTNode child : newChildren ) {
       subQueryAST.addChild(child);
     }
+    
+    subQueryDiagnostic.setAddGroupByClause();
 
     return groupBy;
   }
@@ -895,6 +928,11 @@ public class QBSubQuery implements ISubQ
     return numOfCorrelationExprsAddedToSQSelect;
   }
   
+    
+  public QBSubQueryRewrite getDiagnostic() {
+    return subQueryDiagnostic;
+  }
+  
   public QBSubQuery getSubQuery() {
     return this;
   }

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java Wed Apr 30 15:45:49 2014
@@ -2217,7 +2217,7 @@ public class SemanticAnalyzer extends Ba
       /*
        * Clone the Search AST; apply all rewrites on the clone.
        */
-      ASTNode clonedSearchCond = (ASTNode) ParseDriver.adaptor.dupTree(searchCond);
+      ASTNode clonedSearchCond = (ASTNode) SubQueryUtils.adaptor.dupTree(searchCond);
       List<ASTNode> subQueries = SubQueryUtils.findSubQueries(clonedSearchCond);
 
       for(int i=0; i < subQueries.size(); i++) {
@@ -2230,6 +2230,11 @@ public class SemanticAnalyzer extends Ba
         QBSubQuery subQuery = SubQueryUtils.buildSubQuery(qb.getId(),
             sqIdx, subQueryAST, originalSubQueryAST, ctx);
 
+        if ( !forHavingClause ) {
+          qb.setWhereClauseSubQueryPredicate(subQuery);
+        } else {
+          qb.setHavingClauseSubQueryPredicate(subQuery);
+        }
         String havingInputAlias = null;
 
         if ( forHavingClause ) {

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzerFactory.java Wed Apr 30 15:45:49 2014
@@ -155,6 +155,8 @@ public final class SemanticAnalyzerFacto
       switch (tree.getToken().getType()) {
       case HiveParser.TOK_EXPLAIN:
         return new ExplainSemanticAnalyzer(conf);
+      case HiveParser.TOK_EXPLAIN_SQ_REWRITE:
+        return new ExplainSQRewriteSemanticAnalyzer(conf);
       case HiveParser.TOK_LOAD:
         return new LoadSemanticAnalyzer(conf);
       case HiveParser.TOK_EXPORT:

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryDiagnostic.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryDiagnostic.java?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryDiagnostic.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryDiagnostic.java Wed Apr 30 15:45:49 2014
@@ -0,0 +1,267 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hive.ql.parse;
+
+import org.antlr.runtime.TokenRewriteStream;
+import org.apache.hadoop.hive.ql.Context;
+
+
+/*
+ * Contains functionality that helps with understanding how a SubQuery was rewritten.
+ */
+public class SubQueryDiagnostic {
+
+  static QBSubQueryRewrite getRewrite(QBSubQuery subQuery, 
+      TokenRewriteStream stream,
+      Context ctx) {
+    if (ctx.getExplain()) {
+      return new QBSubQueryRewrite(subQuery, stream);
+    } else {
+      return new QBSubQueryRewriteNoop(subQuery, stream);
+    }
+  }
+  
+  /*
+   * Responsible for capturing SubQuery rewrites and providing the rewritten query
+   * as SQL.
+   */
+  public static class QBSubQueryRewrite {
+    QBSubQuery subQuery;
+    TokenRewriteStream stream;
+    
+    /*
+     * the rewritten where Clause
+     */
+    String whereClause;
+    
+    /*
+     * any additions to the SubQueries Select Clause.
+     */
+    String selectClauseAdditions;
+    
+    /*
+     * additions to the Group By Clause.
+     */
+    String gByClauseAdditions;
+    boolean addGroupByClause;
+    
+    String joiningCondition;
+    
+    String outerQueryPostJoinCond;
+      
+    
+    QBSubQueryRewrite(QBSubQuery subQuery,
+        TokenRewriteStream stream) {
+      this.subQuery = subQuery;
+      this.stream = stream;
+    }
+    
+    public String getRewrittenQuery() {
+
+      ASTNode sqAST = subQuery.getSubQueryAST();
+
+      if (whereClause != null) {
+        ASTNode whereAST = (ASTNode) sqAST.getChild(1).getChild(2);
+        stream.replace(subQuery.getAlias(), 
+            whereAST.getTokenStartIndex(), 
+            whereAST.getTokenStopIndex(),
+            whereClause);
+      }
+
+      if (selectClauseAdditions != null) {
+        ASTNode selectClause = (ASTNode) sqAST.getChild(1).getChild(1);
+        stream.insertAfter(subQuery.getAlias(),
+            selectClause.getTokenStopIndex(), selectClauseAdditions);
+      }
+
+      if (gByClauseAdditions != null) {
+        if (!addGroupByClause) {
+          ASTNode groupBy = (ASTNode) sqAST.getChild(1).getChild(3);
+          stream.insertAfter(subQuery.getAlias(),
+              groupBy.getTokenStopIndex(), gByClauseAdditions);
+        }
+        else {
+          gByClauseAdditions = " group by " + gByClauseAdditions;
+          stream.insertAfter(subQuery.getAlias(),
+              sqAST.getTokenStopIndex() - 1, gByClauseAdditions);
+        }
+      }
+      
+      try {
+        return  
+        stream.toString(subQuery.getAlias(), 
+            sqAST.getTokenStartIndex(),
+            sqAST.getTokenStopIndex())
+             + " " + subQuery.getAlias();
+      } finally {
+        stream.deleteProgram(subQuery.getAlias());
+      }
+    }
+    
+    public String getJoiningCondition() {
+      return joiningCondition;
+    }
+    
+    void addWhereClauseRewrite(ASTNode predicate) {
+      String cond = stream.toString(predicate.getTokenStartIndex(), predicate.getTokenStopIndex());
+      addWhereClauseRewrite(cond);
+    }
+    
+    void addWhereClauseRewrite(String cond) {
+      whereClause = whereClause == null ? "where " : whereClause + " and ";
+      whereClause += cond;
+    }
+    
+    void addSelectClauseRewrite(ASTNode selectExpr, String alias) {
+      if ( selectClauseAdditions == null ) {
+        selectClauseAdditions = "";
+      }
+      
+      selectClauseAdditions += ", " + 
+          stream.toString(selectExpr.getTokenStartIndex(), selectExpr.getTokenStopIndex()) +
+          " as " + alias;
+    }
+    
+    void setAddGroupByClause() {
+      this.addGroupByClause = true;
+    }
+    
+    
+    void addGByClauseRewrite(ASTNode selectExpr) {
+      if ( gByClauseAdditions == null ) {
+        gByClauseAdditions = "";
+      }
+      
+      if ( !addGroupByClause || !gByClauseAdditions.equals("") ) {
+        gByClauseAdditions += ", ";
+      }
+      
+      gByClauseAdditions += stream.toString(
+          selectExpr.getTokenStartIndex(), 
+          selectExpr.getTokenStopIndex());
+    }
+  
+    /*
+     * joinCond represents a correlated predicate.
+     * leftIsRewritten, rightIsRewritten indicates if either side has been replaced by a column alias.
+     * 
+     * If a side is not rewritten, we get its text from the tokenstream. 
+     * For rewritten conditions we form the text based on the table and column reference.
+     */
+    void addJoinCondition(ASTNode joinCond, boolean leftIsRewritten, boolean rightIsRewritten) {
+      StringBuilder b = new StringBuilder();
+      
+      if ( joiningCondition == null ) {
+        joiningCondition = " on ";
+      } else {
+        b.append(" and ");
+      }
+      addCondition(b, (ASTNode) joinCond.getChild(0), leftIsRewritten);
+      b.append(" = ");
+      addCondition(b, (ASTNode) joinCond.getChild(1), rightIsRewritten);
+      
+      joiningCondition += b.toString();
+    }
+    
+    private void addCondition(StringBuilder b, ASTNode cond, boolean rewritten) {
+      if ( !rewritten ) {
+        b.append(stream.toString(cond.getTokenStartIndex(), cond.getTokenStopIndex()));
+      } else {
+        addReference(b, cond);
+      }
+    }
+    
+    private void addReference(StringBuilder b, ASTNode ref) {
+      if ( ref.getType() == HiveParser.DOT ) {
+        b.append(ref.getChild(0).getChild(0).getText()).
+        append(".").
+        append(ref.getChild(1).getText());
+      } else {
+        b.append(ref.getText());
+      }
+    }
+    
+    void addPostJoinCondition(ASTNode cond) {
+      StringBuilder b = new StringBuilder();
+      addReference(b, (ASTNode) cond.getChild(1));
+      outerQueryPostJoinCond = b.toString() + " is null";
+    }
+    
+    public String getOuterQueryPostJoinCond() {
+      return outerQueryPostJoinCond;
+    }
+  }
+
+  /*
+   * In the non explain code path, we don't need to track Query rewrites.
+   * All add fns during Plan generation are Noops.
+   * If the get Rewrite methods are called, an UnsupportedOperationException is thrown.
+   */
+  public static class QBSubQueryRewriteNoop extends QBSubQueryRewrite {
+
+    QBSubQueryRewriteNoop(QBSubQuery subQuery, TokenRewriteStream stream) {
+      super(subQuery, stream);
+    }
+
+    @Override
+    public final String getRewrittenQuery() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    public final String getJoiningCondition() {
+      throw new UnsupportedOperationException();
+    }
+
+    @Override
+    final void addWhereClauseRewrite(ASTNode predicate) {
+    }
+
+    @Override
+    final void addWhereClauseRewrite(String cond) {
+    }
+
+    @Override
+    final void addSelectClauseRewrite(ASTNode selectExpr, String alias) {
+    }
+
+    @Override
+    final void setAddGroupByClause() {
+    }
+
+    @Override
+    final void addGByClauseRewrite(ASTNode selectExpr) {
+    }
+
+    @Override
+    final void addJoinCondition(ASTNode joinCond, boolean leftIsRewritten,
+        boolean rightIsRewritten) {
+    }
+
+    @Override
+    final void addPostJoinCondition(ASTNode cond) {
+    }
+
+    @Override
+    public final String getOuterQueryPostJoinCond() {
+      throw new UnsupportedOperationException();
+    }
+    
+  }
+  
+}
\ No newline at end of file

Modified: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java?rev=1591363&r1=1591362&r2=1591363&view=diff
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java (original)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/parse/SubQueryUtils.java Wed Apr 30 15:45:49 2014
@@ -22,6 +22,7 @@ import java.util.ArrayList;
 import java.util.List;
 import java.util.Map;
 
+import org.antlr.runtime.tree.CommonTreeAdaptor;
 import org.apache.hadoop.hive.ql.Context;
 import org.apache.hadoop.hive.ql.ErrorMsg;
 import org.apache.hadoop.hive.ql.exec.ColumnInfo;
@@ -630,6 +631,12 @@ public class SubQueryUtils {
     public String getOuterQueryId();
   };
 
+    
+  /*
+   * Using CommonTreeAdaptor because the Adaptor in ParseDriver doesn't carry
+   * the token indexes when duplicating a Tree.
+   */
+  static final CommonTreeAdaptor adaptor = new CommonTreeAdaptor();
 }
 
 

Added: hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/plan/ExplainSQRewriteWork.java
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/plan/ExplainSQRewriteWork.java?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/plan/ExplainSQRewriteWork.java (added)
+++ hive/trunk/ql/src/java/org/apache/hadoop/hive/ql/plan/ExplainSQRewriteWork.java Wed Apr 30 15:45:49 2014
@@ -0,0 +1,61 @@
+/**
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.hadoop.hive.ql.plan;
+
+import java.io.Serializable;
+
+import org.apache.hadoop.hive.ql.Context;
+import org.apache.hadoop.hive.ql.parse.ASTNode;
+import org.apache.hadoop.hive.ql.parse.QB;
+
+public class ExplainSQRewriteWork implements Serializable {
+  private static final long serialVersionUID = 1L;
+  
+  private String resFile;
+  private QB qb;
+  private ASTNode ast;
+  private Context ctx;
+  
+  
+  public ExplainSQRewriteWork() {
+  }
+
+  public ExplainSQRewriteWork(String resFile, QB qb, ASTNode ast, Context ctx) {
+    this.resFile = resFile;
+    this.qb = qb;
+    this.ast = ast;
+    this.ctx = ctx;
+  }
+
+  public String getResFile() {
+    return resFile;
+  }
+  
+  public QB getQb() {
+    return qb;
+  }
+
+  public ASTNode getAst() {
+    return ast;
+  }
+
+  public Context getCtx() {
+    return ctx;
+  }
+  
+}

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_exists_explain_rewrite.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_exists_explain_rewrite.q?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_exists_explain_rewrite.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_exists_explain_rewrite.q Wed Apr 30 15:45:49 2014
@@ -0,0 +1,22 @@
+-- no agg, corr
+explain rewrite
+select * 
+from src b 
+where exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+;
+
+-- sq in from
+explain rewrite
+select * 
+from (select * 
+      from src b 
+      where exists 
+          (select a.key 
+          from src a 
+          where b.value = a.value  and a.key = b.key and a.value > 'val_9')
+     ) a
+;
\ No newline at end of file

Added: hive/trunk/ql/src/test/queries/clientpositive/subquery_in_explain_rewrite.q
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/queries/clientpositive/subquery_in_explain_rewrite.q?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/test/queries/clientpositive/subquery_in_explain_rewrite.q (added)
+++ hive/trunk/ql/src/test/queries/clientpositive/subquery_in_explain_rewrite.q Wed Apr 30 15:45:49 2014
@@ -0,0 +1,109 @@
+DROP TABLE part;
+
+-- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+);
+
+DROP TABLE lineitem;
+CREATE TABLE lineitem (L_ORDERKEY      INT,
+                                L_PARTKEY       INT,
+                                L_SUPPKEY       INT,
+                                L_LINENUMBER    INT,
+                                L_QUANTITY      DOUBLE,
+                                L_EXTENDEDPRICE DOUBLE,
+                                L_DISCOUNT      DOUBLE,
+                                L_TAX           DOUBLE,
+                                L_RETURNFLAG    STRING,
+                                L_LINESTATUS    STRING,
+                                l_shipdate      STRING,
+                                L_COMMITDATE    STRING,
+                                L_RECEIPTDATE   STRING,
+                                L_SHIPINSTRUCT  STRING,
+                                L_SHIPMODE      STRING,
+                                L_COMMENT       STRING)
+ROW FORMAT DELIMITED
+FIELDS TERMINATED BY '|';
+
+
+-- non agg, non corr
+explain rewrite
+ select * 
+from src 
+where src.key in (select key from src s1 where s1.key > '9')
+;
+
+-- non agg, corr
+explain rewrite
+select * 
+from src b 
+where b.key in
+        (select a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+;
+
+-- agg, non corr
+explain rewrite
+select p_name, p_size 
+from 
+part where part.p_size in 
+	(select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	)
+;
+
+-- agg, corr
+explain rewrite
+select p_mfgr, p_name, p_size 
+from part b where b.p_size in 
+	(select min(p_size) 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2 and b.p_mfgr = a.p_mfgr
+	)
+;
+
+-- distinct, corr
+explain rewrite
+select * 
+from src b 
+where b.key in
+        (select distinct a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+;
+
+-- non agg, non corr, windowing
+explain rewrite
+select p_mfgr, p_name, p_size 
+from part 
+where part.p_size in 
+  (select first_value(p_size) over(partition by p_mfgr order by p_size) from part)
+;
+
+-- non agg, non corr, with join in Parent Query
+explain rewrite
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR')
+;
+
+-- non agg, corr, with join in Parent Query
+explain rewrite
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR' and l_linenumber = li.l_linenumber)
+;

Added: hive/trunk/ql/src/test/results/clientpositive/subquery_exists_explain_rewrite.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientpositive/subquery_exists_explain_rewrite.q.out?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientpositive/subquery_exists_explain_rewrite.q.out (added)
+++ hive/trunk/ql/src/test/results/clientpositive/subquery_exists_explain_rewrite.q.out Wed Apr 30 15:45:49 2014
@@ -0,0 +1,76 @@
+PREHOOK: query: -- no agg, corr
+explain rewrite
+select * 
+from src b 
+where exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+PREHOOK: type: QUERY
+POSTHOOK: query: -- no agg, corr
+explain rewrite
+select * 
+from src b 
+where exists 
+  (select a.key 
+  from src a 
+  where b.value = a.value  and a.key = b.key and a.value > 'val_9'
+  )
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select a.key, a.value as sq_corr_0, a.key as sq_corr_1 
+  from src a 
+  where a.value > 'val_9'
+  ) sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on b.value = sq_1.sq_corr_0 and sq_1.sq_corr_1 = b.key
+
+Rewritten Query:
+select * 
+from src b  left semi join (select a.key, a.value as sq_corr_0, a.key as sq_corr_1 
+  from src a 
+  where a.value > 'val_9'
+  ) sq_1  on b.value = sq_1.sq_corr_0 and sq_1.sq_corr_1 = b.key 
+where 1 = 1
+PREHOOK: query: -- sq in from
+explain rewrite
+select * 
+from (select * 
+      from src b 
+      where exists 
+          (select a.key 
+          from src a 
+          where b.value = a.value  and a.key = b.key and a.value > 'val_9')
+     ) a
+PREHOOK: type: QUERY
+POSTHOOK: query: -- sq in from
+explain rewrite
+select * 
+from (select * 
+      from src b 
+      where exists 
+          (select a.key 
+          from src a 
+          where b.value = a.value  and a.key = b.key and a.value > 'val_9')
+     ) a
+POSTHOOK: type: QUERY
+
+Where Clause for Query Block 'a'  Rewritten SubQuery:
+(select a.key, a.value as sq_corr_0, a.key as sq_corr_1 
+          from src a 
+          where a.value > 'val_9') sq_1
+
+Where Clause for Query Block 'a'  SubQuery Joining Condition:
+ on b.value = sq_1.sq_corr_0 and sq_1.sq_corr_1 = b.key
+
+Rewritten Query:
+select * 
+from (select * 
+      from src b  left semi join (select a.key, a.value as sq_corr_0, a.key as sq_corr_1 
+          from src a 
+          where a.value > 'val_9') sq_1  on b.value = sq_1.sq_corr_0 and sq_1.sq_corr_1 = b.key 
+      where 1 = 1
+     ) a

Added: hive/trunk/ql/src/test/results/clientpositive/subquery_in_explain_rewrite.q.out
URL: http://svn.apache.org/viewvc/hive/trunk/ql/src/test/results/clientpositive/subquery_in_explain_rewrite.q.out?rev=1591363&view=auto
==============================================================================
--- hive/trunk/ql/src/test/results/clientpositive/subquery_in_explain_rewrite.q.out (added)
+++ hive/trunk/ql/src/test/results/clientpositive/subquery_in_explain_rewrite.q.out Wed Apr 30 15:45:49 2014
@@ -0,0 +1,323 @@
+PREHOOK: query: DROP TABLE part
+PREHOOK: type: DROPTABLE
+POSTHOOK: query: DROP TABLE part
+POSTHOOK: type: DROPTABLE
+PREHOOK: query: -- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+POSTHOOK: query: -- data setup
+CREATE TABLE part( 
+    p_partkey INT,
+    p_name STRING,
+    p_mfgr STRING,
+    p_brand STRING,
+    p_type STRING,
+    p_size INT,
+    p_container STRING,
+    p_retailprice DOUBLE,
+    p_comment STRING
+)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@part
+PREHOOK: query: DROP TABLE lineitem
+PREHOOK: type: DROPTABLE
+POSTHOOK: query: DROP TABLE lineitem
+POSTHOOK: type: DROPTABLE
+PREHOOK: query: CREATE TABLE lineitem (L_ORDERKEY      INT,
+                                L_PARTKEY       INT,
+                                L_SUPPKEY       INT,
+                                L_LINENUMBER    INT,
+                                L_QUANTITY      DOUBLE,
+                                L_EXTENDEDPRICE DOUBLE,
+                                L_DISCOUNT      DOUBLE,
+                                L_TAX           DOUBLE,
+                                L_RETURNFLAG    STRING,
+                                L_LINESTATUS    STRING,
+                                l_shipdate      STRING,
+                                L_COMMITDATE    STRING,
+                                L_RECEIPTDATE   STRING,
+                                L_SHIPINSTRUCT  STRING,
+                                L_SHIPMODE      STRING,
+                                L_COMMENT       STRING)
+ROW FORMAT DELIMITED
+FIELDS TERMINATED BY '|'
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+POSTHOOK: query: CREATE TABLE lineitem (L_ORDERKEY      INT,
+                                L_PARTKEY       INT,
+                                L_SUPPKEY       INT,
+                                L_LINENUMBER    INT,
+                                L_QUANTITY      DOUBLE,
+                                L_EXTENDEDPRICE DOUBLE,
+                                L_DISCOUNT      DOUBLE,
+                                L_TAX           DOUBLE,
+                                L_RETURNFLAG    STRING,
+                                L_LINESTATUS    STRING,
+                                l_shipdate      STRING,
+                                L_COMMITDATE    STRING,
+                                L_RECEIPTDATE   STRING,
+                                L_SHIPINSTRUCT  STRING,
+                                L_SHIPMODE      STRING,
+                                L_COMMENT       STRING)
+ROW FORMAT DELIMITED
+FIELDS TERMINATED BY '|'
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@lineitem
+PREHOOK: query: -- non agg, non corr
+explain rewrite
+ select * 
+from src 
+where src.key in (select key from src s1 where s1.key > '9')
+PREHOOK: type: QUERY
+POSTHOOK: query: -- non agg, non corr
+explain rewrite
+ select * 
+from src 
+where src.key in (select key from src s1 where s1.key > '9')
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select key from src s1 where s1.key > '9') sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on src.key = sq_1.key
+
+Rewritten Query:
+select * 
+from src  left semi join (select key from src s1 where s1.key > '9') sq_1  on src.key = sq_1.key 
+where 1 = 1
+PREHOOK: query: -- non agg, corr
+explain rewrite
+select * 
+from src b 
+where b.key in
+        (select a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+PREHOOK: type: QUERY
+POSTHOOK: query: -- non agg, corr
+explain rewrite
+select * 
+from src b 
+where b.key in
+        (select a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select a.key, a.value as sq_corr_0 
+         from src a 
+         where a.key > '9'
+        ) sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on b.value = sq_1.sq_corr_0 and b.key = sq_1.key
+
+Rewritten Query:
+select * 
+from src b  left semi join (select a.key, a.value as sq_corr_0 
+         from src a 
+         where a.key > '9'
+        ) sq_1  on b.value = sq_1.sq_corr_0 and b.key = sq_1.key 
+where 1 = 1
+PREHOOK: query: -- agg, non corr
+explain rewrite
+select p_name, p_size 
+from 
+part where part.p_size in 
+	(select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	)
+PREHOOK: type: QUERY
+POSTHOOK: query: -- agg, non corr
+explain rewrite
+select p_name, p_size 
+from 
+part where part.p_size in 
+	(select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	)
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	) sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on part.p_size = sq_1._c0
+
+Rewritten Query:
+select p_name, p_size 
+from 
+part  left semi join (select avg(p_size) 
+	 from (select p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	) sq_1  on part.p_size = sq_1._c0 where 1 = 1
+PREHOOK: query: -- agg, corr
+explain rewrite
+select p_mfgr, p_name, p_size 
+from part b where b.p_size in 
+	(select min(p_size) 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2 and b.p_mfgr = a.p_mfgr
+	)
+PREHOOK: type: QUERY
+POSTHOOK: query: -- agg, corr
+explain rewrite
+select p_mfgr, p_name, p_size 
+from part b where b.p_size in 
+	(select min(p_size) 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2 and b.p_mfgr = a.p_mfgr
+	)
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select min(p_size), a.p_mfgr as sq_corr_0 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	 group by  group by a.p_mfgr) sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on b.p_mfgr = sq_1.sq_corr_0 and b.p_size = sq_1._c0
+
+Rewritten Query:
+select p_mfgr, p_name, p_size 
+from part b  left semi join (select min(p_size), a.p_mfgr as sq_corr_0 
+	 from (select p_mfgr, p_size, rank() over(partition by p_mfgr order by p_size) as r from part) a 
+	 where r <= 2
+	 group by a.p_mfgr) sq_1  on b.p_mfgr = sq_1.sq_corr_0 and b.p_size = sq_1._c0 where 1 = 1
+PREHOOK: query: -- distinct, corr
+explain rewrite
+select * 
+from src b 
+where b.key in
+        (select distinct a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+PREHOOK: type: QUERY
+POSTHOOK: query: -- distinct, corr
+explain rewrite
+select * 
+from src b 
+where b.key in
+        (select distinct a.key 
+         from src a 
+         where b.value = a.value and a.key > '9'
+        )
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select distinct a.key, a.value as sq_corr_0 
+         from src a 
+         where a.key > '9'
+        ) sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on b.value = sq_1.sq_corr_0 and b.key = sq_1.key
+
+Rewritten Query:
+select * 
+from src b  left semi join (select distinct a.key, a.value as sq_corr_0 
+         from src a 
+         where a.key > '9'
+        ) sq_1  on b.value = sq_1.sq_corr_0 and b.key = sq_1.key 
+where 1 = 1
+PREHOOK: query: -- non agg, non corr, windowing
+explain rewrite
+select p_mfgr, p_name, p_size 
+from part 
+where part.p_size in 
+  (select first_value(p_size) over(partition by p_mfgr order by p_size) from part)
+PREHOOK: type: QUERY
+POSTHOOK: query: -- non agg, non corr, windowing
+explain rewrite
+select p_mfgr, p_name, p_size 
+from part 
+where part.p_size in 
+  (select first_value(p_size) over(partition by p_mfgr order by p_size) from part)
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select first_value(p_size) over(partition by p_mfgr order by p_size) from part) sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on part.p_size = sq_1._wcol0
+
+Rewritten Query:
+select p_mfgr, p_name, p_size 
+from part  left semi join (select first_value(p_size) over(partition by p_mfgr order by p_size) from part) sq_1  on part.p_size = sq_1._wcol0 
+where 1 = 1
+PREHOOK: query: -- non agg, non corr, with join in Parent Query
+explain rewrite
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR')
+PREHOOK: type: QUERY
+POSTHOOK: query: -- non agg, non corr, with join in Parent Query
+explain rewrite
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR')
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select l_orderkey from lineitem where l_shipmode = 'AIR') sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on li.l_orderkey = sq_1.l_orderkey
+
+Rewritten Query:
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey  left semi join (select l_orderkey from lineitem where l_shipmode = 'AIR') sq_1  on li.l_orderkey = sq_1.l_orderkey 
+where li.l_linenumber = 1 and
+ 1 = 1
+PREHOOK: query: -- non agg, corr, with join in Parent Query
+explain rewrite
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR' and l_linenumber = li.l_linenumber)
+PREHOOK: type: QUERY
+POSTHOOK: query: -- non agg, corr, with join in Parent Query
+explain rewrite
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey 
+where li.l_linenumber = 1 and
+ li.l_orderkey in (select l_orderkey from lineitem where l_shipmode = 'AIR' and l_linenumber = li.l_linenumber)
+POSTHOOK: type: QUERY
+
+Where Clause  Rewritten SubQuery:
+(select l_orderkey, l_linenumber as sq_corr_0 from lineitem where l_shipmode = 'AIR') sq_1
+
+Where Clause  SubQuery Joining Condition:
+ on sq_1.sq_corr_0 = li.l_linenumber and li.l_orderkey = sq_1.l_orderkey
+
+Rewritten Query:
+select p.p_partkey, li.l_suppkey 
+from (select distinct l_partkey as p_partkey from lineitem) p join lineitem li on p.p_partkey = li.l_partkey  left semi join (select l_orderkey, l_linenumber as sq_corr_0 from lineitem where l_shipmode = 'AIR') sq_1  on sq_1.sq_corr_0 = li.l_linenumber and li.l_orderkey = sq_1.l_orderkey 
+where li.l_linenumber = 1 and
+ 1 = 1