This is an automated email from the ASF dual-hosted git repository.

soumyakanti3578 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hive.git


The following commit(s) were added to refs/heads/master by this push:
     new 64fdebb1cc2 HIVE-29580: CBO: Ambiguous column reference not detected 
in some CTE/CTAS/other queries (#6676)
64fdebb1cc2 is described below

commit 64fdebb1cc22bc2dfd1ee9dd6eca8903215a7443
Author: Konstantin Bereznyakov <[email protected]>
AuthorDate: Thu Sep 17 13:38:14 2026 -0700

    HIVE-29580: CBO: Ambiguous column reference not detected in some 
CTE/CTAS/other queries (#6676)
---
 .../org/apache/hadoop/hive/ql/exec/ColumnInfo.java |  20 ++
 .../hadoop/hive/ql/parse/CalcitePlanner.java       |  46 +++++
 .../hadoop/hive/ql/parse/SemanticAnalyzer.java     |   2 +
 .../hive/ql/parse/rewrite/MergeRewriter.java       |   8 +-
 .../parse/rewrite/sql/MultiInsertSqlGenerator.java |   9 +
 .../parse/type/JoinCondTypeCheckProcFactory.java   |   2 +
 .../hive/ql/parse/type/TypeCheckProcFactory.java   |  16 ++
 .../apache/hadoop/hive/ql/exec/TestColumnInfo.java |  40 ++++
 .../hadoop/hive/ql/parse/TestSemanticAnalyzer.java | 181 +++++++++++++++++++
 .../rewrite/sql/TestMultiInsertSqlGenerator.java   |  90 +++++++++
 .../type/TestJoinCondTypeCheckProcFactory.java     | 109 +++++++++++
 .../ql/parse/type/TestTypeCheckProcFactory.java    | 201 +++++++++++++--------
 .../queries/clientnegative/ambiguous_col_ctas.q    |   8 +
 .../clientnegative/ambiguous_col_distinct_window.q |   4 +
 .../clientnegative/ambiguous_col_join_cond.q       |   7 +
 .../ambiguous_col_join_cond_unqual.q               |   5 +
 .../clientnegative/ambiguous_col_join_using.q      |   1 +
 .../ambiguous_col_lateral_view_alias.q             |   7 +
 .../clientnegative/ambiguous_col_unqualified_ref.q |   8 +
 .../clientpositive/ambiguous_col_noncbo_baseline.q |  55 ++++++
 .../clientpositive/ambiguous_col_rejected.q        |  25 +++
 .../clientpositive/ambiguous_col_tolerated.q       |  16 ++
 .../ambiguous_col_union_distinct_tolerated.q       |  10 +
 .../ambiguous_col_unreferenced_tolerated.q         |  16 ++
 ql/src/test/queries/clientpositive/cross_prod_3.q  |   4 +-
 .../queries/clientpositive/limit_join_transpose.q  |  24 ++-
 .../results/clientnegative/ambiguous_col.q.out     |   2 +-
 .../results/clientnegative/ambiguous_col_2.q.out   |   2 +-
 .../clientnegative/ambiguous_col_ctas.q.out        |   1 +
 .../ambiguous_col_distinct_window.q.out            |   1 +
 .../clientnegative/ambiguous_col_join_cond.q.out   |   1 +
 .../ambiguous_col_join_cond_unqual.q.out           |   1 +
 .../clientnegative/ambiguous_col_join_using.q.out  |   1 +
 .../ambiguous_col_lateral_view_alias.q.out         |   9 +
 .../ambiguous_col_unqualified_ref.q.out            |   1 +
 .../cbo_ambiguous_colref_in_gby.q.out              |   2 +-
 .../clientnegative/cte_col_alias_clash.q.out       |   2 +-
 .../llap/ambiguous_col_noncbo_baseline.q.out       |  44 +++++
 .../llap/ambiguous_col_rejected.q.out              |   5 +
 .../llap/ambiguous_col_tolerated.q.out             | 110 +++++++++++
 .../ambiguous_col_union_distinct_tolerated.q.out   |  20 ++
 .../ambiguous_col_unreferenced_tolerated.q.out     | 101 +++++++++++
 .../results/clientpositive/llap/cross_prod_3.q.out |   4 +-
 .../clientpositive/llap/limit_join_transpose.q.out |  40 ++--
 44 files changed, 1143 insertions(+), 118 deletions(-)

diff --git a/ql/src/java/org/apache/hadoop/hive/ql/exec/ColumnInfo.java 
b/ql/src/java/org/apache/hadoop/hive/ql/exec/ColumnInfo.java
index 9565d163697..e52a89b3575 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/exec/ColumnInfo.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/exec/ColumnInfo.java
@@ -60,6 +60,12 @@ public class ColumnInfo implements Serializable {
 
   private boolean isHiddenVirtualCol;
 
+  /**
+   * Deliberately excluded from equals/hashCode/isSameColumnForRR: a marked 
and an unmarked
+   * copy of a column are still the same column for RowResolver purposes 
(HIVE-29580).
+   */
+  private boolean ambiguousName;
+
   private String typeName;
 
   private final boolean nullable;
@@ -130,9 +136,23 @@ public ColumnInfo(ColumnInfo columnInfo) {
     this.isVirtualCol = columnInfo.getIsVirtualCol();
     this.isHiddenVirtualCol = columnInfo.isHiddenVirtualCol();
     this.nullable = columnInfo.nullable;
+    this.ambiguousName = columnInfo.ambiguousName;
     this.setType(columnInfo.getType());
   }
 
+  /**
+   * True when this column's alias collided with another column's at a 
subquery/CTE boundary:
+   * the column stays usable positionally (star expansion, count(*)) but a 
user-written by-name
+   * reference is ambiguous and must be rejected.
+   */
+  public boolean hasAmbiguousName() {
+    return ambiguousName;
+  }
+
+  public void setAmbiguousName(boolean ambiguousName) {
+    this.ambiguousName = ambiguousName;
+  }
+
   public String getTypeName() {
     return this.typeName;
   }
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 ec77bbf3215..a8140689a71 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
@@ -3630,6 +3630,8 @@ private RelNode genGBLogicalPlan(QB qb, RelNode srcRel) 
throws SemanticException
       // SEL%SEL% rule.
       ASTNode selExprList = qb.getParseInfo().getSelForClause(destClauseName);
       SubQueryUtils.checkForTopLevelSubqueries(selExprList);
+      List<Integer> clearedAmbiguousPositions = new ArrayList<>();
+      List<ColumnInfo> clearedAmbiguousColumns = null;
       if (selExprList.getToken().getType() == HiveParser.TOK_SELECTDI
           && selExprList.getChildCount() == 1 && 
selExprList.getChild(0).getChildCount() == 1) {
         ASTNode node = (ASTNode) selExprList.getChild(0).getChild(0);
@@ -3637,6 +3639,17 @@ private RelNode genGBLogicalPlan(QB qb, RelNode srcRel) 
throws SemanticException
           // As we said before, here we use genSelectLogicalPlan to rewrite 
AllColRef
           srcRel = genSelectLogicalPlan(qb, srcRel, srcRel, null, null, 
true).getKey();
           RowResolver rr = relToHiveRR.get(srcRel);
+          // Clear the HIVE-29580 ambiguity markers on this rewrite-private 
projection (its
+          // ColumnInfos are genColListRegex copies; the subquery's own 
RowResolver keeps its
+          // markers) so genSelectDIAST's synthesized by-name references type 
check; reapplied
+          // to the group by output below so that references crossing this 
boundary still fail.
+          clearedAmbiguousColumns = rr.getColumnInfos();
+          for (int i = 0; i < clearedAmbiguousColumns.size(); i++) {
+            if (clearedAmbiguousColumns.get(i).hasAmbiguousName()) {
+              clearedAmbiguousPositions.add(i);
+              clearedAmbiguousColumns.get(i).setAmbiguousName(false);
+            }
+          }
           qbp.setSelExprForClause(destClauseName, genSelectDIAST(rr));
         }
       }
@@ -3777,6 +3790,16 @@ private RelNode genGBLogicalPlan(QB qb, RelNode srcRel) 
throws SemanticException
         groupByRel = genGBRelNode(groupByExpressions, aggregations, 
groupingSets, srcRel);
         relToHiveColNameCalcitePosMap.put(groupByRel, 
buildHiveToCalciteColumnMap(groupByOutputRowResolver));
         relToHiveRR.put(groupByRel, groupByOutputRowResolver);
+        // Reapply the markers cleared for the DISTINCT * rewrite above; its 
group by output is
+        // positionally one key per input column (no aggregations, no grouping 
sets). Copy the
+        // user-visible names too, so a rejection resolving against this 
exprResolver RR (e.g.
+        // a HAVING reference) reads "c in t" rather than the expression tree.
+        for (int position : clearedAmbiguousPositions) {
+          ColumnInfo gbColInfo = 
groupByOutputRowResolver.getColumnInfos().get(position);
+          gbColInfo.setAmbiguousName(true);
+          gbColInfo.setAlias(clearedAmbiguousColumns.get(position).getAlias());
+          
gbColInfo.setTabAlias(clearedAmbiguousColumns.get(position).getTabAlias());
+        }
       }
 
       return groupByRel;
@@ -4452,6 +4475,13 @@ && isRegex(
             ColumnInfo colInfo = new 
ColumnInfo(SemanticAnalyzer.getColumnInternalName(pos),
                 
TypeInfoUtils.getStandardWritableObjectInspectorFromTypeInfo(typeInfo),
                 tabAlias, false);
+            if (expression instanceof RexInputRef inputRef) {
+              // Carry the HIVE-29580 marker through this projection. Only 
expression-map
+              // resolutions (the DISTINCT * rewrite's synthesized references) 
reach here with a
+              // marked source; user-written ones already failed 
checkAmbiguousName in genRexNode.
+              ColumnInfo sourceColInfo = 
inputRR.getColumnInfos().get(inputRef.getIndex());
+              colInfo.setAmbiguousName(sourceColInfo.hasAmbiguousName());
+            }
             outputRR.put(tabAlias, colAlias, colInfo);
 
             pos = Integer.valueOf(pos.intValue() + 1);
@@ -4569,6 +4599,7 @@ && isRegex(
           ColumnInfo colInfo = outputRR.getColumnInfos().get(i);
           ColumnInfo newColInfo = new ColumnInfo(colInfo.getInternalName(),
               colInfo.getType(), colInfo.getTabAlias(), 
colInfo.getIsVirtualCol());
+          newColInfo.setAmbiguousName(colInfo.hasAmbiguousName());
           groupByOutputRowResolver.put(colInfo.getTabAlias(), 
colInfo.getAlias(), newColInfo);
           if (gbyKeyExpressions != null && gbyKeyExpressions.size() == 
outputRR.getColumnInfos().size()) {
             groupByOutputRowResolver.putExpression(gbyKeyExpressions.get(i), 
colInfo);
@@ -4906,11 +4937,26 @@ private RelNode genLogicalPlan(QB qb, boolean 
outerMostQB,
           ColumnInfo newCi = new ColumnInfo(colInfo);
           newCi.setTabAlias(alias);
           if (i < targetColNames.size()) {
+            // An explicit column list disambiguates positionally; a collision 
with an unlisted
+            // column is re-marked when that later column's turn reaches the 
branch below.
             tmp[1] = targetColNames.get(i);
             newCi.setAlias(tmp[1]);
+            newCi.setAmbiguousName(false);
           } else if ("".equals(tmp[0]) || tmp[1] == null) {
             // ast expression is not a valid column name for table
             tmp[1] = colInfo.getInternalName();
+          } else {
+            ColumnInfo clashingColInfo = newRR.get(alias, tmp[1]);
+            if (clashingColInfo != null) {
+              // Duplicate alias escaping the subquery boundary: tolerated for 
positional use
+              // (HIVE-19770), but poison the name so a later by-name 
reference fails (HIVE-29580).
+              // Binding the duplicate to its internal name here is 
deliberate, not redundant:
+              // putWithCheck would otherwise do it via its own fallback AND 
call keepAmbiguousInfo,
+              // whose reference-time throw in RowResolver.get would then 
shadow this marker with a
+              // differently formatted message. Do not "simplify" this line 
away.
+              clashingColInfo.setAmbiguousName(true);
+              tmp[1] = colInfo.getInternalName();
+            }
           }
           newRR.putWithCheck(alias, tmp[1], colInfo.getInternalName(), newCi);
         }
diff --git a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
index 9139355fe47..cadb097c4d4 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/SemanticAnalyzer.java
@@ -4015,6 +4015,7 @@ Integer genColListRegex(String colRegex, String tabAlias, 
ASTNode sel,
             colList.add(Pair.of(colInfo, colSrcRR));
             oColInfo = new ColumnInfo(getColumnInternalName(pos), 
colInfo.getType(),
                 colInfo.getTabAlias(), colInfo.getIsVirtualCol(), 
colInfo.isHiddenVirtualCol());
+            oColInfo.setAmbiguousName(colInfo.hasAmbiguousName());
             inputColsProcessed.put(colInfo, oColInfo);
           }
           if (ensureUniqueCols) {
@@ -4102,6 +4103,7 @@ Integer genColListRegex(String colRegex, String tabAlias, 
ASTNode sel,
           colList.add(Pair.of(colInfo, input));
           oColInfo = new ColumnInfo(getColumnInternalName(pos), 
colInfo.getType(),
               colInfo.getTabAlias(), colInfo.getIsVirtualCol(), 
colInfo.isHiddenVirtualCol());
+          oColInfo.setAmbiguousName(colInfo.hasAmbiguousName());
           inputColsProcessed.put(colInfo, oColInfo);
         }
         assert nonNull(tmp);
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/MergeRewriter.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/MergeRewriter.java
index e398a211fc4..726a18a0f61 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/MergeRewriter.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/MergeRewriter.java
@@ -114,7 +114,13 @@ private void handleSource(boolean hasWhenNotMatchedClause, 
String sourceAlias, S
     sqlGenerator.append("FROM\n");
     sqlGenerator.append("(SELECT ");
     sqlGenerator.appendAcidSelectColumns(Operation.MERGE);
-    sqlGenerator.appendAllColsOfTargetTable();
+    if (sqlGenerator.getTargetTable().hasNonNativePartitionSupport()) {
+      // non-native partition columns are ordinary data columns of the row 
schema
+      sqlGenerator.appendAllColsOfTargetTable();
+    } else {
+      // native partition columns were already emitted by 
appendAcidSelectColumns above
+      sqlGenerator.appendNonPartitionColsOfTargetTable();
+    }
     addSourceColumnsForRowLineage(isRowLineageSupported, sqlGenerator, "", 
conf);
     sqlGenerator.append(" FROM ").appendTargetTableName().append(") ");
     sqlGenerator.appendSubQueryAlias();
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/sql/MultiInsertSqlGenerator.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/sql/MultiInsertSqlGenerator.java
index 0189c445269..88d69fd4bf2 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/sql/MultiInsertSqlGenerator.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/rewrite/sql/MultiInsertSqlGenerator.java
@@ -170,6 +170,15 @@ public void appendAllColsOfTargetTable(String prefix) {
   public void appendAllColsOfTargetTable() {
     appendCols(targetTable.getAllCols(), FieldSchema::getName);
   }
+
+  /**
+   * Appends the target table's non-partition columns. For a natively 
partitioned MERGE target
+   * the partition columns are already emitted by appendAcidSelectColumns; 
emitting them again
+   * would give the rewritten projection duplicate column names (HIVE-29580).
+   */
+  public void appendNonPartitionColsOfTargetTable() {
+    appendCols(targetTable.getCols(), FieldSchema::getName);
+  }
   
   public <T> void appendCols(List<T> columns, Function<T, String> 
stringConverter) {
     appendCols(columns, null, null, stringConverter);
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/JoinCondTypeCheckProcFactory.java
 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/JoinCondTypeCheckProcFactory.java
index 7785d7556c2..e1c6e2a3821 100644
--- 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/JoinCondTypeCheckProcFactory.java
+++ 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/JoinCondTypeCheckProcFactory.java
@@ -88,6 +88,7 @@ public Object process(Node nd, Stack<Node> stack, 
NodeProcessorCtx procCtx,
       if (!qualifiedAccess) {
         colInfo = getColInfo(ctx, null, tableOrCol, expr);
         // It's a column.
+        checkAmbiguousName(colInfo);
         return exprFactory.createColumnRefExpr(colInfo, ctx.getInputRRList());
       } else if (hasTableAlias(ctx, tableOrCol, expr)) {
         return null;
@@ -180,6 +181,7 @@ protected T processQualifiedColRef(TypeCheckCtx ctx, 
ASTNode expr,
             ErrorMsg.INVALID_COLUMN.getMsg(), expr.getChild(1)), expr);
         return null;
       }
+      checkAmbiguousName(colInfo);
       ColumnInfo newColumnInfo = new ColumnInfo(colInfo);
       newColumnInfo.setTabAlias(tableAlias);
       List<RowResolver> listRR = new ArrayList<>(jctx.getInputRRList());
diff --git 
a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/TypeCheckProcFactory.java 
b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/TypeCheckProcFactory.java
index 638d96cfa2d..261942cd93f 100644
--- a/ql/src/java/org/apache/hadoop/hive/ql/parse/type/TypeCheckProcFactory.java
+++ b/ql/src/java/org/apache/hadoop/hive/ql/parse/type/TypeCheckProcFactory.java
@@ -595,6 +595,19 @@ protected IntervalExprProcessor getIntervalExprProcessor() 
{
     return new IntervalExprProcessor();
   }
 
+  /**
+   * Rejects a by-name reference to a column marked ambiguous at a 
subquery/CTE boundary
+   * (HIVE-29580). Call after each by-name resolution of a user-written column 
reference;
+   * expression-map resolutions (processGByExpr) stay unchecked so Hive's own 
rewrites can
+   * reference marked columns.
+   */
+  static void checkAmbiguousName(ColumnInfo colInfo) throws SemanticException {
+    if (colInfo != null && colInfo.hasAmbiguousName()) {
+      throw new SemanticException(ErrorMsg.AMBIGUOUS_COLUMN.getMsg(
+          colInfo.getAlias() + " in " + colInfo.getTabAlias()));
+    }
+  }
+
   /**
    * Processor for table columns.
    */
@@ -660,6 +673,7 @@ public Object process(Node nd, Stack<Node> stack, 
NodeProcessorCtx procCtx,
             return null;
           }
           // It's a column.
+          checkAmbiguousName(colInfo);
           return exprFactory.toExpr(colInfo, usedRR, offset);
         } else {
           // It's a table alias.
@@ -694,6 +708,7 @@ public Object process(Node nd, Stack<Node> stack, 
NodeProcessorCtx procCtx,
           }
         } else {
           // It's a column.
+          checkAmbiguousName(colInfo);
           return exprFactory.toExpr(colInfo, usedRR, offset);
         }
       }
@@ -1300,6 +1315,7 @@ protected T processQualifiedColRef(TypeCheckCtx ctx, 
ASTNode expr,
             ErrorMsg.INVALID_COLUMN.getMsg(), expr.getChild(1)), expr);
         return null;
       }
+      checkAmbiguousName(colInfo);
       return exprFactory.toExpr(colInfo, usedRR, offset);
     }
 
diff --git a/ql/src/test/org/apache/hadoop/hive/ql/exec/TestColumnInfo.java 
b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestColumnInfo.java
new file mode 100644
index 00000000000..fbbd2ea2cd2
--- /dev/null
+++ b/ql/src/test/org/apache/hadoop/hive/ql/exec/TestColumnInfo.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestColumnInfo {
+
+  @Test
+  public void testAmbiguousNameDefaultsToFalse() {
+    ColumnInfo colInfo = new ColumnInfo("_col0", 
TypeInfoFactory.stringTypeInfo, "t", false);
+    Assert.assertFalse(colInfo.hasAmbiguousName());
+  }
+
+  @Test
+  public void testCopyConstructorPreservesAmbiguousName() {
+    ColumnInfo original = new ColumnInfo("_col0", 
TypeInfoFactory.stringTypeInfo, "t", false);
+    original.setAmbiguousName(true);
+    Assert.assertTrue(new ColumnInfo(original).hasAmbiguousName());
+  }
+}
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/parse/TestSemanticAnalyzer.java 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/TestSemanticAnalyzer.java
index 2b47e690195..59a8c105a5f 100644
--- a/ql/src/test/org/apache/hadoop/hive/ql/parse/TestSemanticAnalyzer.java
+++ b/ql/src/test/org/apache/hadoop/hive/ql/parse/TestSemanticAnalyzer.java
@@ -22,6 +22,7 @@
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertThrows;
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 import static org.mockito.ArgumentMatchers.any;
@@ -34,13 +35,16 @@
 import static org.mockito.Mockito.when;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.TreeSet;
 
 import com.google.common.collect.Sets;
+import org.antlr.runtime.CommonToken;
 import org.apache.hadoop.hive.common.MaterializationSnapshot;
 import org.apache.hadoop.hive.common.type.Date;
 import org.apache.hadoop.hive.conf.HiveConf;
@@ -56,6 +60,7 @@
 import org.apache.hadoop.hive.ql.QueryProperties.QueryType;
 import org.apache.hadoop.hive.ql.QueryState;
 import org.apache.hadoop.hive.ql.cache.results.QueryResultsCache;
+import org.apache.hadoop.hive.ql.exec.ColumnInfo;
 import org.apache.hadoop.hive.ql.exec.FileSinkOperator;
 import org.apache.hadoop.hive.ql.exec.Operator;
 import org.apache.hadoop.hive.ql.lockmgr.DbTxnManager;
@@ -67,6 +72,7 @@
 import org.apache.hadoop.hive.ql.security.HadoopDefaultAuthenticator;
 import org.apache.hadoop.hive.ql.session.SessionState;
 import org.apache.hadoop.hive.serde2.io.DateWritableV2;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
 import org.junit.AfterClass;
 import org.junit.Assert;
 import org.junit.BeforeClass;
@@ -546,4 +552,179 @@ private void testMaterializeCTEUsesDDLFactory(boolean 
cboEnabled) throws Excepti
           cteAnalyzer[0] instanceof CreateTableAnalyzer);
     }
   }
+
+  // ==== HIVE-29580: duplicate column aliases escaping a subquery/CTE 
boundary ====
+
+  private BaseSemanticAnalyzer analyzeWithCbo(String query) throws Exception {
+    return analyzeWithCbo(query, false);
+  }
+
+  private BaseSemanticAnalyzer analyzeWithCbo(String query, boolean 
returnPath) throws Exception {
+    HiveConf cboConf = new HiveConf(conf);
+    cboConf.setBoolVar(HiveConf.ConfVars.HIVE_CBO_ENABLED, true);
+    cboConf.setBoolVar(HiveConf.ConfVars.HIVE_CBO_RETPATH_HIVEOP, returnPath);
+    SessionState.start(cboConf);
+    Context ctx = new Context(cboConf);
+    ASTNode astNode = ParseUtils.parse(query, ctx);
+    QueryState queryState = new 
QueryState.Builder().withHiveConf(cboConf).build();
+    BaseSemanticAnalyzer analyzer = SemanticAnalyzerFactory.get(queryState, 
astNode);
+    analyzer.initCtx(ctx);
+    try {
+      analyzer.analyze(astNode, ctx);
+    } finally {
+      analyzer.endAnalysis(astNode);
+    }
+    return analyzer;
+  }
+
+  private void assertCboRejectsAmbiguous(String query, String 
expectedReference) {
+    SemanticException e = assertThrows(SemanticException.class, () -> 
analyzeWithCbo(query));
+    assertTrue(e.getMessage(),
+        e.getMessage().contains("Ambiguous column reference " + 
expectedReference));
+  }
+
+  @Test
+  public void testCboRejectsAmbiguousReferenceAcrossCteBoundary() {
+    assertCboRejectsAmbiguous(
+        "with bse as (select 'a' as c, 'b' as c), tpm as (select * from bse) 
select tpm.c from tpm",
+        "c in tpm");
+  }
+
+  @Test
+  public void testCboAmbiguityMarkerSurvivesWindowingProjection() {
+    assertCboRejectsAmbiguous(
+        "select x.c from (select distinct *, rank() over (order by d) r"
+            + " from (select 'a' as c, 'b' as c, 'x' as d) t) x",
+        "c in x");
+  }
+
+  @Test
+  public void testCboToleratesUnionDistinctWithDuplicateAliases() throws 
Exception {
+    // UNION DISTINCT is rewritten into SELECT DISTINCT * whose group by 
references are
+    // synthesized by genSelectDIAST; despite the duplicate output alias this 
must compile
+    assertNotNull(analyzeWithCbo("select x.key, z.value, y.value"
+        + " from table1 x join table2 y on x.key = y.key"
+        + " join (select * from table1 union select * from table2) z on 
x.value = z.value"
+        + " union"
+        + " select x.key, z.value, y.value"
+        + " from table1 x join table2 y on x.key = y.key"
+        + " join (select * from table1 union select * from table2) z on 
x.value = z.value"));
+  }
+
+  @Test
+  public void testCboRejectsReferenceLaunderedThroughDistinctStar() {
+    // the DISTINCT * rewrite clears the markers for its synthesized group by 
references;
+    // they must be reapplied to the group by output or the outer reference 
silently binds
+    assertCboRejectsAmbiguous(
+        "select x.c from (select distinct * from (select 'a' as c, 'b' as c) 
t) x",
+        "c in x");
+  }
+
+  @Test
+  public void testCboRejectsReferenceAcrossUnionDistinctBoundary() {
+    // UNION DISTINCT goes through the same DISTINCT * rewrite as above
+    assertCboRejectsAmbiguous(
+        "select z.c from (select 'a' as c, 'b' as c union select 'x' as c, 'y' 
as c) z",
+        "c in z");
+  }
+
+  @Test
+  public void testCboRejectsHavingReferenceOverDistinctDuplicate() {
+    // resolves against the group by output's exprResolver RR; also pins the 
readable
+    // message (without the alias copy in the re-mark loop it prints the 
expression tree)
+    assertCboRejectsAmbiguous(
+        "select distinct * from (select 'a' as c, 'b' as c) t having c = 'a'",
+        "c in t");
+  }
+
+  @Test
+  public void testCboToleratesCteColumnListRenamingDuplicateColumns() throws 
Exception {
+    // the explicit column list renames positionally, so renamed.a is 
unambiguous
+    assertNotNull(analyzeWithCbo(
+        "with bse as (select 'a' as c, 'b' as c), renamed(a, b) as (select * 
from bse)"
+            + " select renamed.a from renamed"));
+  }
+
+  @Test
+  public void 
testCboRejectsReferenceWhenUnlistedColumnCollidesWithColumnListName() {
+    // the column list renames only the first column; the second column's own 
alias collides
+    // with the assigned name, so the reference is ambiguous again
+    assertCboRejectsAmbiguous(
+        "with renamed(a) as (select 'x' as c, 'y' as a) select renamed.a from 
renamed",
+        "a in renamed");
+  }
+
+  @Test
+  public void testCboAmbiguityChecksAreReturnPathInvariant() throws Exception {
+    // the marker mechanism runs during plan construction, which both values of
+    // hive.cbo.returnpath.hiveop share; retpath=true additionally drives the 
operator
+    // conversion over the marked (and re-aliased) group by RowResolvers
+    String[] rejected = {
+        "with bse as (select 'a' as c, 'b' as c), tpm as (select * from bse) 
select tpm.c from tpm",
+        "select x.c from (select distinct * from (select 'a' as c, 'b' as c) 
t) x",
+        "select z.c from (select 'a' as c, 'b' as c union select 'x' as c, 'y' 
as c) z"};
+    String[] tolerated = {
+        "select * from (select 'a' as c, 'b' as c) t",
+        "select distinct * from (select 'a' as c, 'b' as c) t",
+        "with bse as (select 'a' as c, 'b' as c), renamed(a, b) as (select * 
from bse)"
+            + " select renamed.a from renamed"};
+    for (String query : rejected) {
+      SemanticException e = assertThrows(SemanticException.class, () -> 
analyzeWithCbo(query, true));
+      assertTrue(e.getMessage(), e.getMessage().contains("Ambiguous column 
reference"));
+    }
+    for (String query : tolerated) {
+      assertNotNull(analyzeWithCbo(query, true));
+    }
+  }
+
+  private static ColumnInfo stringCol(String internalName, String tab, String 
alias, boolean markedAmbiguous) {
+    ColumnInfo colInfo = new ColumnInfo(internalName, 
TypeInfoFactory.stringTypeInfo, tab, false);
+    colInfo.setAlias(alias);
+    colInfo.setAmbiguousName(markedAmbiguous);
+    return colInfo;
+  }
+
+  private SemanticAnalyzer newAnalyzerForDirectCalls() throws Exception {
+    SessionState.start(conf);
+    QueryState queryState = new 
QueryState.Builder().withHiveConf(conf).build();
+    SemanticAnalyzer analyzer = new SemanticAnalyzer(queryState);
+    analyzer.initCtx(new Context(conf));
+    // genColListRegex consults tableMask, which analyzeInternal normally 
initializes
+    analyzer.tableMask = new TableMask(analyzer, conf, true);
+    return analyzer;
+  }
+
+  private static ASTNode allColRef() {
+    return new ASTNode(new CommonToken(HiveParser.TOK_ALLCOLREF, 
"TOK_ALLCOLREF"));
+  }
+
+  @Test
+  public void testGenColListRegexPropagatesAmbiguousNameMarker() throws 
Exception {
+    SemanticAnalyzer analyzer = newAnalyzerForDirectCalls();
+    RowResolver input = new RowResolver();
+    input.put("t", "c", stringCol("_c0", "t", "c", true));
+    input.put("t", "d", stringCol("_c1", "t", "d", false));
+    RowResolver output = new RowResolver();
+
+    analyzer.genColListRegex(".*", "t", allColRef(), new ArrayList<>(),
+        new HashSet<>(), input, null, 0, output, new 
ArrayList<>(Arrays.asList("t")), false);
+
+    assertTrue(output.get("t", "c").hasAmbiguousName());
+    assertFalse(output.get("t", "d").hasAmbiguousName());
+  }
+
+  @Test
+  public void testGenColListRegexPropagatesAmbiguousNameMarkerForNamedJoin() 
throws Exception {
+    SemanticAnalyzer analyzer = newAnalyzerForDirectCalls();
+    RowResolver colSrcRR = new RowResolver();
+    colSrcRR.put("l", "c", stringCol("_l0", "l", "c", true));
+    colSrcRR.put("r", "c", stringCol("_r0", "r", "c", false));
+    colSrcRR.setNamedJoinInfo(new NamedJoinInfo(Arrays.asList("l", "r"), 
Arrays.asList("c"), JoinType.INNER));
+    RowResolver output = new RowResolver();
+
+    analyzer.genColListRegex(".*", null, allColRef(), new ArrayList<>(),
+        new HashSet<>(), colSrcRR, colSrcRR, 0, output, new 
ArrayList<>(Arrays.asList("l", "r")), false);
+
+    assertTrue(output.get("l", "c").hasAmbiguousName());
+  }
 }
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/parse/rewrite/sql/TestMultiInsertSqlGenerator.java
 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/rewrite/sql/TestMultiInsertSqlGenerator.java
new file mode 100644
index 00000000000..766c73762eb
--- /dev/null
+++ 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/rewrite/sql/TestMultiInsertSqlGenerator.java
@@ -0,0 +1,90 @@
+/*
+ * 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.rewrite.sql;
+
+import java.util.Arrays;
+import java.util.Collections;
+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.Context.Operation;
+import org.apache.hadoop.hive.ql.metadata.Table;
+import org.junit.Assert;
+import org.junit.Test;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class TestMultiInsertSqlGenerator {
+
+  private static final List<FieldSchema> DATA_COLS = Arrays.asList(
+      new FieldSchema("a", "int", null), new FieldSchema("b", "string", null));
+  private static final List<FieldSchema> ALL_COLS = Arrays.asList(
+      new FieldSchema("a", "int", null), new FieldSchema("b", "string", null),
+      new FieldSchema("p", "string", null));
+  private static final HiveConf CONF = new HiveConf();
+
+  private static MultiInsertSqlGenerator generator(boolean 
nonNativePartitionSupport) {
+    Table table = mock(Table.class);
+    when(table.getCols()).thenReturn(DATA_COLS);
+    when(table.getAllCols()).thenReturn(ALL_COLS);
+    
when(table.hasNonNativePartitionSupport()).thenReturn(nonNativePartitionSupport);
+    return new MultiInsertSqlGenerator(table, "t", CONF, null) {
+      @Override
+      public void appendAcidSelectColumns(Operation operation) {
+        // ACID select columns are irrelevant to these column-append tests; 
keep the stub inert
+      }
+
+      @Override
+      public List<String> getDeleteValues(Operation operation) {
+        return Collections.emptyList();
+      }
+
+      @Override
+      public List<String> getSortKeys(Operation operation) {
+        return Collections.emptyList();
+      }
+    };
+  }
+
+  /**
+   * HIVE-29580: for natively partitioned tables the partition columns are 
emitted by
+   * appendAcidSelectColumns, so they must be omitted here or the rewritten 
projection contains
+   * duplicate column names.
+   */
+  @Test
+  public void testAppendNonPartitionColsOfTargetTableOmitsPartitionCols() {
+    MultiInsertSqlGenerator generator = generator(false);
+    generator.appendNonPartitionColsOfTargetTable();
+    Assert.assertEquals("`a`, `b`", generator.toString());
+  }
+
+  /**
+   * Non-native tables carry partition columns as ordinary data columns, so 
MergeRewriter
+   * selects appendAllColsOfTargetTable for them.
+   */
+  @Test
+  public void testAppendAllColsOfTargetTable() {
+    MultiInsertSqlGenerator generator = generator(true);
+    generator.appendAllColsOfTargetTable();
+    Assert.assertEquals("`a`, `b`, `p`", generator.toString());
+  }
+}
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestJoinCondTypeCheckProcFactory.java
 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestJoinCondTypeCheckProcFactory.java
new file mode 100644
index 00000000000..d8472a65543
--- /dev/null
+++ 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestJoinCondTypeCheckProcFactory.java
@@ -0,0 +1,109 @@
+/*
+ * 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.type;
+
+import java.util.Map;
+
+import org.antlr.runtime.CommonToken;
+import org.apache.calcite.jdbc.JavaTypeFactoryImpl;
+import org.apache.calcite.rex.RexBuilder;
+import org.apache.calcite.rex.RexNode;
+import org.apache.hadoop.hive.ql.exec.ColumnInfo;
+import org.apache.hadoop.hive.ql.optimizer.calcite.HiveTypeSystemImpl;
+import org.apache.hadoop.hive.ql.parse.ASTNode;
+import org.apache.hadoop.hive.ql.parse.HiveParser;
+import org.apache.hadoop.hive.ql.parse.JoinType;
+import org.apache.hadoop.hive.ql.parse.RowResolver;
+import org.apache.hadoop.hive.ql.parse.SemanticException;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
+import org.junit.Assert;
+import org.junit.Test;
+
+/**
+ * Tests for the ambiguity checks in JoinCondTypeCheckProcFactory 
(HIVE-29580): a join condition
+ * referencing a duplicate-named column that escaped a subquery boundary must 
be rejected, both
+ * through the qualified (JoinCondDefaultExprProcessor) and the unqualified
+ * (JoinCondColumnExprProcessor) resolution paths. The expressions are type 
checked through the
+ * same walker entry point the planner uses.
+ */
+public class TestJoinCondTypeCheckProcFactory {
+
+  private static ASTNode node(int type, String text) {
+    return new ASTNode(new CommonToken(type, text));
+  }
+
+  private static ASTNode unqualifiedRef(String col) {
+    ASTNode tableOrCol = node(HiveParser.TOK_TABLE_OR_COL, "TOK_TABLE_OR_COL");
+    tableOrCol.addChild(node(HiveParser.Identifier, col));
+    return tableOrCol;
+  }
+
+  private static ASTNode qualifiedRef(String tab, String col) {
+    ASTNode dot = node(HiveParser.DOT, ".");
+    dot.addChild(unqualifiedRef(tab));
+    dot.addChild(node(HiveParser.Identifier, col));
+    return dot;
+  }
+
+  private static RowResolver singleColRR(String tab, String col, boolean 
markedAmbiguous) {
+    RowResolver rr = new RowResolver();
+    ColumnInfo colInfo = new ColumnInfo(tab + "_" + col, 
TypeInfoFactory.stringTypeInfo, tab, false);
+    colInfo.setAlias(col);
+    colInfo.setAmbiguousName(markedAmbiguous);
+    rr.put(tab, col, colInfo);
+    return rr;
+  }
+
+  private static Map<ASTNode, RexNode> typeCheck(ASTNode expr, boolean 
leftColumnMarked)
+      throws SemanticException {
+    RowResolver leftRR = singleColRR("t", "c", leftColumnMarked);
+    RowResolver rightRR = singleColRR("u", "e", false);
+    RexBuilder rexBuilder = new RexBuilder(new JavaTypeFactoryImpl(new 
HiveTypeSystemImpl()));
+    JoinTypeCheckCtx ctx = new JoinTypeCheckCtx(leftRR, rightRR, rexBuilder, 
JoinType.INNER);
+    return RexNodeTypeCheck.genExprNodeJoinCond(expr, ctx, rexBuilder);
+  }
+
+  private static void assertThrowsAmbiguous(ASTNode expr) {
+    SemanticException e = Assert.assertThrows(SemanticException.class, () -> 
typeCheck(expr, true));
+    Assert.assertTrue(e.getMessage(), e.getMessage().contains("Ambiguous 
column reference c in t"));
+  }
+
+  @Test
+  public void testQualifiedRefToMarkedColumnThrows() {
+    assertThrowsAmbiguous(qualifiedRef("t", "c"));
+  }
+
+  @Test
+  public void testUnqualifiedRefToMarkedColumnThrows() {
+    assertThrowsAmbiguous(unqualifiedRef("c"));
+  }
+
+  @Test
+  public void testQualifiedRefToCleanColumnResolves() throws SemanticException 
{
+    ASTNode expr = qualifiedRef("t", "c");
+    Assert.assertNotNull(typeCheck(expr, false).get(expr));
+  }
+
+  @Test
+  public void testUnqualifiedRefToCleanColumnResolves() throws 
SemanticException {
+    ASTNode expr = unqualifiedRef("c");
+    Assert.assertNotNull(typeCheck(expr, false).get(expr));
+  }
+}
diff --git 
a/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestTypeCheckProcFactory.java
 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestTypeCheckProcFactory.java
index a65eaafb6a4..7309ff12c1e 100644
--- 
a/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestTypeCheckProcFactory.java
+++ 
b/ql/src/test/org/apache/hadoop/hive/ql/parse/type/TestTypeCheckProcFactory.java
@@ -22,14 +22,18 @@
 import java.util.Arrays;
 import java.util.Collection;
 
+import org.apache.hadoop.hive.ql.exec.ColumnInfo;
+import org.apache.hadoop.hive.ql.parse.SemanticException;
 import 
org.apache.hadoop.hive.ql.parse.type.TypeCheckProcFactory.DefaultExprProcessor;
 import org.apache.hadoop.hive.ql.plan.ExprNodeConstantDesc;
 import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils;
 import 
org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorUtils.PrimitiveTypeEntry;
 import org.apache.hadoop.hive.serde2.typeinfo.PrimitiveTypeInfo;
+import org.apache.hadoop.hive.serde2.typeinfo.TypeInfoFactory;
 import org.junit.Assert;
 import org.junit.Before;
 import org.junit.Test;
+import org.junit.experimental.runners.Enclosed;
 import org.junit.runner.RunWith;
 import org.junit.runners.Parameterized;
 import org.junit.runners.Parameterized.Parameters;
@@ -38,107 +42,144 @@
 import org.mockito.MockitoAnnotations;
 
 /**
- * Parametrized test for the TypeCheckProcFactory.
- *
+ * Tests for the TypeCheckProcFactory.
  */
-@RunWith(Parameterized.class)
+@RunWith(Enclosed.class)
 public class TestTypeCheckProcFactory {
-  @Mock
-  private PrimitiveTypeInfo typeInfo;
-  @Mock
-  private ExprNodeConstantDesc nodeDesc;
-
-  private DefaultExprProcessor testSubject;
-
-  @Parameters(name = "{1}")
-  public static Collection<Object[]> data() {
-    return Arrays.asList(new Object[][] {{"127", 
PrimitiveObjectInspectorUtils.byteTypeEntry, (byte) 127, true},
-        {"32767", PrimitiveObjectInspectorUtils.shortTypeEntry, (short) 32767, 
true},
-        {"2147483647", PrimitiveObjectInspectorUtils.intTypeEntry, 2147483647, 
true},
-        {"9223372036854775807", PrimitiveObjectInspectorUtils.longTypeEntry, 
9223372036854775807L, true},
-        {"111.1", PrimitiveObjectInspectorUtils.floatTypeEntry, 111.1f, false},
-        {"111.1", PrimitiveObjectInspectorUtils.doubleTypeEntry, 111.1d, 
false}});
-  }
 
-  private final BigDecimal maxValue;
-  private final PrimitiveTypeEntry constType;
-  private final Object expectedValue;
-  private final boolean intType;
-
-  public TestTypeCheckProcFactory(String maxValue, PrimitiveTypeEntry 
constType, Object expectedValue,
-      boolean intType) {
-    this.maxValue = new BigDecimal(maxValue);
-    this.constType = constType;
-    this.expectedValue = expectedValue;
-    this.intType = intType;
-  }
+  /**
+   * Parametrized tests for constant interpretation.
+   */
+  @RunWith(Parameterized.class)
+  public static class ConstantInterpretationTest {
+    @Mock
+    private PrimitiveTypeInfo typeInfo;
+    @Mock
+    private ExprNodeConstantDesc nodeDesc;
+
+    private DefaultExprProcessor testSubject;
+
+    @Parameters(name = "{1}")
+    public static Collection<Object[]> data() {
+      return Arrays.asList(new Object[][] {{"127", 
PrimitiveObjectInspectorUtils.byteTypeEntry, (byte) 127, true},
+          {"32767", PrimitiveObjectInspectorUtils.shortTypeEntry, (short) 
32767, true},
+          {"2147483647", PrimitiveObjectInspectorUtils.intTypeEntry, 
2147483647, true},
+          {"9223372036854775807", PrimitiveObjectInspectorUtils.longTypeEntry, 
9223372036854775807L, true},
+          {"111.1", PrimitiveObjectInspectorUtils.floatTypeEntry, 111.1f, 
false},
+          {"111.1", PrimitiveObjectInspectorUtils.doubleTypeEntry, 111.1d, 
false}});
+    }
 
-  @Before
-  public void init() {
-    MockitoAnnotations.initMocks(this);
-    testSubject = ExprNodeTypeCheck.getExprNodeDefaultExprProcessor();
-  }
+    private final BigDecimal maxValue;
+    private final PrimitiveTypeEntry constType;
+    private final Object expectedValue;
+    private final boolean intType;
+
+    public ConstantInterpretationTest(String maxValue, PrimitiveTypeEntry 
constType, Object expectedValue,
+        boolean intType) {
+      this.maxValue = new BigDecimal(maxValue);
+      this.constType = constType;
+      this.expectedValue = expectedValue;
+      this.intType = intType;
+    }
 
-  public void testOneCase(Object constValue) throws Exception {
-    Mockito.when(nodeDesc.getValue()).thenReturn(constValue);
-    Mockito.when(typeInfo.getPrimitiveTypeEntry()).thenReturn(constType);
+    @Before
+    public void init() {
+      MockitoAnnotations.initMocks(this);
+      testSubject = ExprNodeTypeCheck.getExprNodeDefaultExprProcessor();
+    }
 
-    ExprNodeConstantDesc result = (ExprNodeConstantDesc) 
testSubject.interpretNodeAsConstant(typeInfo, nodeDesc);
+    public void testOneCase(Object constValue) throws Exception {
+      Mockito.when(nodeDesc.getValue()).thenReturn(constValue);
+      Mockito.when(typeInfo.getPrimitiveTypeEntry()).thenReturn(constType);
 
-    Assert.assertNotNull(result);
-    Assert.assertEquals(expectedValue, result.getValue());
-  }
+      ExprNodeConstantDesc result = (ExprNodeConstantDesc) 
testSubject.interpretNodeAsConstant(typeInfo, nodeDesc);
 
-  public void testNullCase(Object constValue) throws Exception {
-    Mockito.when(nodeDesc.getValue()).thenReturn(constValue);
-    Mockito.when(typeInfo.getPrimitiveTypeEntry()).thenReturn(constType);
+      Assert.assertNotNull(result);
+      Assert.assertEquals(expectedValue, result.getValue());
+    }
 
-    ExprNodeConstantDesc result = (ExprNodeConstantDesc) 
testSubject.interpretNodeAsConstant(typeInfo, nodeDesc);
+    public void testNullCase(Object constValue) throws Exception {
+      Mockito.when(nodeDesc.getValue()).thenReturn(constValue);
+      Mockito.when(typeInfo.getPrimitiveTypeEntry()).thenReturn(constType);
 
-    Assert.assertNull(result);
-  }
+      ExprNodeConstantDesc result = (ExprNodeConstantDesc) 
testSubject.interpretNodeAsConstant(typeInfo, nodeDesc);
 
-  @Test
-  public void testWithSring() throws Exception {
-    testOneCase(maxValue.toString());
-  }
+      Assert.assertNull(result);
+    }
 
-  @Test
-  public void testWithLSuffix() throws Exception {
-    if (intType) {
-      testOneCase(maxValue.toString() + "L");
+    @Test
+    public void testWithSring() throws Exception {
+      testOneCase(maxValue.toString());
     }
-  }
 
-  @Test
-  public void testWithZeroFraction() throws Exception {
-    if (intType) {
-      testOneCase(maxValue.toString() + ".0");
+    @Test
+    public void testWithLSuffix() throws Exception {
+      if (intType) {
+        testOneCase(maxValue.toString() + "L");
+      }
     }
-  }
 
-  @Test
-  public void testWithFSuffix() throws Exception {
-    testOneCase(maxValue.toString() + "f");
-  }
+    @Test
+    public void testWithZeroFraction() throws Exception {
+      if (intType) {
+        testOneCase(maxValue.toString() + ".0");
+      }
+    }
 
-  @Test
-  public void testWithDSuffix() throws Exception {
-    testOneCase(maxValue.toString() + "D");
-  }
+    @Test
+    public void testWithFSuffix() throws Exception {
+      testOneCase(maxValue.toString() + "f");
+    }
 
-  @Test
-  public void testOverflow() throws Exception {
-    if (intType) {
-      testNullCase(maxValue.add(BigDecimal.valueOf(1L)).toString());
+    @Test
+    public void testWithDSuffix() throws Exception {
+      testOneCase(maxValue.toString() + "D");
     }
-  }
 
-  @Test
-  public void testWithNonZeroFraction() throws Exception {
-    if (intType) {
-      testNullCase("100.1");
+    @Test
+    public void testOverflow() throws Exception {
+      if (intType) {
+        testNullCase(maxValue.add(BigDecimal.valueOf(1L)).toString());
+      }
+    }
+
+    @Test
+    public void testWithNonZeroFraction() throws Exception {
+      if (intType) {
+        testNullCase("100.1");
+      }
     }
   }
 
+  /**
+   * Tests for checkAmbiguousName (HIVE-29580). The planner-side call sites 
are covered by the
+   * ambiguous_col* qtests.
+   */
+  public static class CheckAmbiguousNameTest {
+
+    private static ColumnInfo colInfo() {
+      ColumnInfo colInfo = new ColumnInfo("_col0", 
TypeInfoFactory.stringTypeInfo, "t", false);
+      colInfo.setAlias("c");
+      return colInfo;
+    }
+
+    @Test
+    public void testCheckAmbiguousNameThrows() {
+      ColumnInfo marked = colInfo();
+      marked.setAmbiguousName(true);
+      SemanticException e = Assert.assertThrows(SemanticException.class,
+          () -> TypeCheckProcFactory.checkAmbiguousName(marked));
+      Assert.assertTrue(e.getMessage(), e.getMessage().contains("Ambiguous 
column reference c in t"));
+    }
+
+    @Test
+    public void testCheckAmbiguousNameNoThrow() throws SemanticException {
+      TypeCheckProcFactory.checkAmbiguousName(colInfo());
+    }
+
+    @Test
+    public void testCheckAmbiguousNameNullTolerant() throws SemanticException {
+      TypeCheckProcFactory.checkAmbiguousName(null);
+    }
+  }
 }
diff --git a/ql/src/test/queries/clientnegative/ambiguous_col_ctas.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_ctas.q
new file mode 100644
index 00000000000..7a4d232a134
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_ctas.q
@@ -0,0 +1,8 @@
+-- Cross-alias ambiguous reference in a CTAS: unchecked, one 
arbitrarily-chosen candidate is
+-- silently persisted into the table. Keep this test even if the check ever 
exempts statements
+-- Hive generates for itself (rewritten MERGE/UPDATE/DELETE, materialised 
CTEs): a user CTAS
+-- must never be exempted.
+create table ctas_ambiguous_ref as
+  with bse as (select 'FIRST' as c, 'SECOND' as c),
+       tpm as (select * from bse)
+  select tpm.c from tpm;
diff --git a/ql/src/test/queries/clientnegative/ambiguous_col_distinct_window.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_distinct_window.q
new file mode 100644
index 00000000000..75ad8b3c0d0
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_distinct_window.q
@@ -0,0 +1,4 @@
+-- DISTINCT combined with a windowing function is planned as a GROUP BY over 
all select columns,
+-- whose output RowResolver is rebuilt from fresh ColumnInfo copies; the 
ambiguity marker must
+-- survive that rebuild (and RowResolver.add's copy-constructor, which this 
shape also exercises).
+select x.c from (select distinct *, rank() over (order by d) r from (select 
'a' as c, 'b' as c, 'x' as d) t) x;
diff --git a/ql/src/test/queries/clientnegative/ambiguous_col_join_cond.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_join_cond.q
new file mode 100644
index 00000000000..d48d8215a7f
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_join_cond.q
@@ -0,0 +1,7 @@
+-- the duplicate alias is referenced only in the join condition, via a 
qualified name.
+-- Unparse translation is disabled below on purpose: when it is on, the ON 
clause is also
+-- walked by the generic type check, which would make this test pass even if 
the ambiguity
+-- check in JoinCondTypeCheckProcFactory were removed.
+set hive.materializedview.rewriting.sql=false;
+set hive.materializedview.rewriting.sql.subquery=false;
+select t.d from (select 'a' as c, 'b' as c, 'x' as d) t join (select 'a' as e) 
u on t.c = u.e;
diff --git 
a/ql/src/test/queries/clientnegative/ambiguous_col_join_cond_unqual.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_join_cond_unqual.q
new file mode 100644
index 00000000000..d05f686c6fc
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_join_cond_unqual.q
@@ -0,0 +1,5 @@
+-- same as ambiguous_col_join_cond.q but the reference is unqualified, which 
is resolved by a
+-- different processor override. See that file for why unparse translation is 
disabled here.
+set hive.materializedview.rewriting.sql=false;
+set hive.materializedview.rewriting.sql.subquery=false;
+select t.d from (select 'a' as c, 'b' as c, 'x' as d) t join (select 'a' as e) 
u on c = u.e;
diff --git a/ql/src/test/queries/clientnegative/ambiguous_col_join_using.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_join_using.q
new file mode 100644
index 00000000000..3d87fb4c3f7
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_join_using.q
@@ -0,0 +1 @@
+select t.c from (select * from (select 'a' as c, 'b' as c) s join (select 'a' 
as c) u using (c)) t;
diff --git 
a/ql/src/test/queries/clientnegative/ambiguous_col_lateral_view_alias.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_lateral_view_alias.q
new file mode 100644
index 00000000000..1007f67229a
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_lateral_view_alias.q
@@ -0,0 +1,7 @@
+-- The lateral view reuses the table alias, so the exploded column collides 
with the base table
+-- column under the same table alias. This is caught by the reference-time 
check in
+-- RowResolver.get (ambiguousColumns), not by the duplicate-alias marker: the 
message form
+-- "Ambiguous column reference: t.c" identifies that path. Keep this test: it 
is the only
+-- coverage of that check, which would otherwise look like dead code and get 
removed.
+create table lv_dup_alias (c int, arr array<int>);
+select t.c from lv_dup_alias t lateral view explode(t.arr) t as c;
diff --git a/ql/src/test/queries/clientnegative/ambiguous_col_unqualified_ref.q 
b/ql/src/test/queries/clientnegative/ambiguous_col_unqualified_ref.q
new file mode 100644
index 00000000000..1f9566d23af
--- /dev/null
+++ b/ql/src/test/queries/clientnegative/ambiguous_col_unqualified_ref.q
@@ -0,0 +1,8 @@
+-- The inner CTE references the duplicated alias by an UNQUALIFIED name, which 
is resolved by
+-- TypeCheckProcFactory.ColumnExprProcessor (the "It's a column" branch) 
rather than by
+-- processQualifiedColRef. Every other ambiguity test uses a qualified 
reference, so this is the
+-- only coverage of that check site. The error names the definition-site alias 
(bse), matching
+-- what the non-CBO path reports for the same query.
+with bse as (select 'a' as c, 'b' as c),
+     tpm as (select c from bse)
+select tpm.c from tpm;
diff --git a/ql/src/test/queries/clientpositive/ambiguous_col_noncbo_baseline.q 
b/ql/src/test/queries/clientpositive/ambiguous_col_noncbo_baseline.q
new file mode 100644
index 00000000000..c117945e564
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/ambiguous_col_noncbo_baseline.q
@@ -0,0 +1,55 @@
+--! qt:dataset:src
+-- HIVE-29580: baseline of the non-CBO planner's pre-existing duplicate-alias 
strictness, left
+-- untouched by the ticket. Every statement fails; the FAILED messages pair to 
statements by
+-- order (hive.cli.errors.ignore). Section 1: definition-time rejections that 
CBO tolerates
+-- since HIVE-19770/HIVE-20215 (CBO mirror: 
ambiguous_col_unreferenced_tolerated.q).
+-- Section 2: ambiguous references, which CBO also rejects 
(ambiguous_col_rejected.q).
+set hive.cli.errors.ignore=true;
+set hive.cbo.enable=false;
+
+-- ==== definition-time rejections: the duplicate is never referenced by name 
====
+
+-- another column of the derived table is referenced
+select t.d from (select 'a' as c, 'b' as c, 'x' as d) t;
+
+-- same, through a CTE
+with c1 as (select 'a' as c, 'b' as c, 'x' as d)
+select d from c1;
+
+-- only counted, no column referenced
+select count(*) from (select key, key from src) subq;
+
+-- duplicate created by a wildcard join expansion
+create table wj3 (k int, v int);
+create table wj4 (k int, w int);
+select t.v from (select a.*, b.* from wj3 a join wj4 b on a.k = b.k) t;
+
+-- duplicate crosses two nested star boundaries
+select * from (select * from (select 'a' as c, 'b' as c) a) b;
+
+-- duplicate defined inside an EXISTS subquery
+select key from src a where exists (select 'x' as c, 'y' as c from src b where 
b.key = a.key);
+
+-- duplicate defined inside an EXISTS in HAVING
+select value, count(1) from src group by value having exists (select 'x' as c, 
'y' as c from src b where b.value = src.value);
+
+-- ==== reference-time rejections: the duplicate name is referenced ====
+
+-- expression aliased onto an existing column name, then referenced
+FROM (SELECT key, concat(value) AS key FROM src) a SELECT a.key;
+
+-- the HIVE-20215 self-join example
+create table t1nc (c1 int);
+explain select t.c1 from (select t11.c1, t12.c1 from t1nc as t11 inner join 
t1nc as t12 on t11.c1 = t12.c1) as t;
+
+-- qualified reference through a consuming CTE
+with bse as (select 'a' as c, 'b' as c),
+     tpm as (select * from bse)
+select tpm.c from tpm;
+
+-- reference into a UNION ALL branch
+select t.c from (select 'a' as c, 'b' as c union all select 'x', 'y') t;
+
+-- ambiguous reference used as a GROUP BY key
+create table t1gnc (a int);
+select s.a from (select a, a from t1gnc) s group by s.a;
diff --git a/ql/src/test/queries/clientpositive/ambiguous_col_rejected.q 
b/ql/src/test/queries/clientpositive/ambiguous_col_rejected.q
new file mode 100644
index 00000000000..b7810b00b53
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/ambiguous_col_rejected.q
@@ -0,0 +1,25 @@
+-- HIVE-29580: by-name references to duplicate-named columns that escaped a 
subquery/CTE
+-- boundary; these used to compile under CBO with the reference silently bound 
to an arbitrary
+-- candidate. hive.cli.errors.ignore keeps every rejection in one file; the 
FAILED messages pair
+-- to statements by order. Mechanism-specific cases live in the clientnegative 
ambiguous_col_*.q
+-- tests; the non-CBO baseline is ambiguous_col_noncbo_baseline.q.
+set hive.cli.errors.ignore=true;
+
+-- the JIRA shape: duplicate alias escapes a CTE, then a qualified reference 
through the
+-- consuming CTE's alias
+with bse as (select 'a' as c, 'b' as c),
+     tpm as (select * from bse)
+select tpm.c from tpm;
+
+-- duplicate alias escapes a UNION ALL branch into the derived-table alias
+select t.c from (select 'a' as c, 'b' as c union all select 'x', 'y') t;
+
+-- the DISTINCT * rewrite must not launder the ambiguity away
+select x.c from (select distinct * from (select 'a' as c, 'b' as c) t) x;
+
+-- same laundering point via the UNION DISTINCT rewrite
+select z.c from (select 'a' as c, 'b' as c union select 'x' as c, 'y' as c) z;
+
+-- explicit column list renames only the first column; the second column's own 
alias collides
+-- with the assigned name, so the reference is ambiguous again
+with renamed(a) as (select 'x' as c, 'y' as a) select renamed.a from renamed;
diff --git a/ql/src/test/queries/clientpositive/ambiguous_col_tolerated.q 
b/ql/src/test/queries/clientpositive/ambiguous_col_tolerated.q
new file mode 100644
index 00000000000..35ab8141cff
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/ambiguous_col_tolerated.q
@@ -0,0 +1,16 @@
+select 'a' as c, 'b' as c;
+select 'a' as c, 'b' as c order by c;
+select * from (select 'a' as c, 'b' as c) t;
+create table dup_alias_ins (x string, y string);
+insert into dup_alias_ins select 'a' as c, 'b' as c;
+select x, y from dup_alias_ins;
+-- no non-CBO mirror for this one: CTE column lists are CBO-only (non-CBO 
ignores them)
+with bse as (select 'a' as c, 'b' as c), renamed(a, b) as (select * from bse) 
select renamed.a from renamed;
+
+set hive.cbo.enable=false;
+
+select 'a' as c, 'b' as c;
+select 'a' as c, 'b' as c order by c;
+select * from (select 'a' as c, 'b' as c) t;
+insert into dup_alias_ins select 'c' as c, 'd' as c;
+select x, y from dup_alias_ins order by x;
diff --git 
a/ql/src/test/queries/clientpositive/ambiguous_col_union_distinct_tolerated.q 
b/ql/src/test/queries/clientpositive/ambiguous_col_union_distinct_tolerated.q
new file mode 100644
index 00000000000..72a791aec4e
--- /dev/null
+++ 
b/ql/src/test/queries/clientpositive/ambiguous_col_union_distinct_tolerated.q
@@ -0,0 +1,10 @@
+-- SORT_QUERY_RESULTS
+-- HIVE-29580: UNION DISTINCT is rewritten into SELECT DISTINCT * over an 
internal alias, and
+-- the rewrite synthesizes by-name group-by references from the RowResolver it 
enumerated.
+-- Duplicate output aliases in the branches must not trip the ambiguity check 
there: the
+-- references are unique by construction. Both statements must compile, 
deduplicate across all
+-- columns, and keep both duplicate columns' values intact.
+
+select 'a' as c, 'b' as c union select 'a', 'b' union select 'a', 'x';
+
+select distinct * from (select 'a' as c, 'b' as c union all select 'a', 'b' 
union all select 'a', 'x') t;
diff --git 
a/ql/src/test/queries/clientpositive/ambiguous_col_unreferenced_tolerated.q 
b/ql/src/test/queries/clientpositive/ambiguous_col_unreferenced_tolerated.q
new file mode 100644
index 00000000000..9461f5f70a0
--- /dev/null
+++ b/ql/src/test/queries/clientpositive/ambiguous_col_unreferenced_tolerated.q
@@ -0,0 +1,16 @@
+--! qt:dataset:src
+-- HIVE-29580: duplicate aliases that are never referenced by name stay 
accepted under CBO
+-- (HIVE-19770/HIVE-20215); the non-CBO planner rejects most of these shapes 
at definition
+-- time, see this file's non-CBO mirror ambiguous_col_noncbo_baseline.q.
+select t.d from (select 'a' as c, 'b' as c, 'x' as d) t;
+with c1 as (select 'a' as c, 'b' as c, 'x' as d)
+select d from c1;
+select count(1) from (select 'a' as c, 'b' as c) t;
+select count(*) from (select key, key from src) subq;
+create table wjt1 (k int, v int);
+create table wjt2 (k int, w int);
+select t.v from (select a.*, b.* from wjt1 a join wjt2 b on a.k = b.k) t;
+select * from (select * from (select 'a' as c, 'b' as c) a) b;
+select count(*) from src a where exists (select 'x' as c, 'y' as c from src b 
where b.key = a.key);
+select count(*) from src where exists (select 'a' as c, 'b' as c from src);
+select count(*) from (select value from src group by value having exists 
(select 'x' as c, 'y' as c from src b where b.value = src.value)) t;
diff --git a/ql/src/test/queries/clientpositive/cross_prod_3.q 
b/ql/src/test/queries/clientpositive/cross_prod_3.q
index a1024f42d16..9efcee56a1e 100644
--- a/ql/src/test/queries/clientpositive/cross_prod_3.q
+++ b/ql/src/test/queries/clientpositive/cross_prod_3.q
@@ -11,4 +11,6 @@ insert overwrite table X_n2 select distinct * from src order 
by key limit 10;
 create table Y_n0 as
 select * from src order by key limit 1;
 
-explain select * from Y_n0, (select * from X_n2 as A join X_n2 as B on 
A.key=B.key) as C where Y_n0.key=C.key;
+-- HIVE-29580: the derived table's columns are aliased explicitly because 
"select *" over the
+-- self-join projects two columns named key (and value), making the C.key 
reference ambiguous.
+explain select * from Y_n0, (select A.key, A.value, B.key as key2, B.value as 
value2 from X_n2 as A join X_n2 as B on A.key=B.key) as C where Y_n0.key=C.key;
diff --git a/ql/src/test/queries/clientpositive/limit_join_transpose.q 
b/ql/src/test/queries/clientpositive/limit_join_transpose.q
index 4c484bd8135..2ac401f292e 100644
--- a/ql/src/test/queries/clientpositive/limit_join_transpose.q
+++ b/ql/src/test/queries/clientpositive/limit_join_transpose.q
@@ -1,6 +1,10 @@
 --! qt:dataset:src1
 --! qt:dataset:src
 
+-- HIVE-29580: the derived tables' columns are aliased explicitly because 
"select *" over the
+-- src2/src3 join projects two columns named key (and value), making the 
src2.key references
+-- ambiguous; the two key candidates are not even equal here since the join is 
on value.
+
 SET hive.vectorized.execution.enabled=false;
 set hive.mapred.mode=nonstrict;
 set hive.optimize.limittranspose=false;
@@ -50,7 +54,7 @@ limit 1;
 explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -58,7 +62,7 @@ limit 1;
 
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -71,7 +75,7 @@ set hive.optimize.limittranspose.reductiontuples=0;
 explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -79,7 +83,7 @@ limit 1;
 
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -107,7 +111,7 @@ limit 1;
 explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -115,7 +119,7 @@ limit 0;
 
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -170,7 +174,7 @@ limit 1 offset 1;
 explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -178,7 +182,7 @@ limit 1 offset 1;
 
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -191,7 +195,7 @@ set hive.optimize.limittranspose.reductiontuples=0;
 explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -199,7 +203,7 @@ limit 1 offset 1;
 
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
diff --git a/ql/src/test/results/clientnegative/ambiguous_col.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col.q.out
index 170e277d0ee..a2915a4a5d3 100644
--- a/ql/src/test/results/clientnegative/ambiguous_col.q.out
+++ b/ql/src/test/results/clientnegative/ambiguous_col.q.out
@@ -1 +1 @@
-FAILED: SemanticException Ambiguous column reference: a.key
+FAILED: SemanticException [Error 10007]: Ambiguous column reference key in a
diff --git a/ql/src/test/results/clientnegative/ambiguous_col_2.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_2.q.out
index bc6fb4d112a..ac4bd4063f2 100644
--- a/ql/src/test/results/clientnegative/ambiguous_col_2.q.out
+++ b/ql/src/test/results/clientnegative/ambiguous_col_2.q.out
@@ -6,4 +6,4 @@ POSTHOOK: query: create table t1(c1 int)
 POSTHOOK: type: CREATETABLE
 POSTHOOK: Output: database:default
 POSTHOOK: Output: default@t1
-FAILED: SemanticException Ambiguous column reference: t.c1
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c1 in t
diff --git a/ql/src/test/results/clientnegative/ambiguous_col_ctas.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_ctas.q.out
new file mode 100644
index 00000000000..a88aa731e43
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_ctas.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in tpm
diff --git 
a/ql/src/test/results/clientnegative/ambiguous_col_distinct_window.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_distinct_window.q.out
new file mode 100644
index 00000000000..a19c1eba9da
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_distinct_window.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in x
diff --git a/ql/src/test/results/clientnegative/ambiguous_col_join_cond.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_join_cond.q.out
new file mode 100644
index 00000000000..58aee7c0894
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_join_cond.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in t
diff --git 
a/ql/src/test/results/clientnegative/ambiguous_col_join_cond_unqual.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_join_cond_unqual.q.out
new file mode 100644
index 00000000000..58aee7c0894
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_join_cond_unqual.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in t
diff --git a/ql/src/test/results/clientnegative/ambiguous_col_join_using.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_join_using.q.out
new file mode 100644
index 00000000000..2f33a44abe8
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_join_using.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in s
diff --git 
a/ql/src/test/results/clientnegative/ambiguous_col_lateral_view_alias.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_lateral_view_alias.q.out
new file mode 100644
index 00000000000..df3a1e7efdd
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_lateral_view_alias.q.out
@@ -0,0 +1,9 @@
+PREHOOK: query: create table lv_dup_alias (c int, arr array<int>)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@lv_dup_alias
+POSTHOOK: query: create table lv_dup_alias (c int, arr array<int>)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@lv_dup_alias
+FAILED: SemanticException Ambiguous column reference: t.c
diff --git 
a/ql/src/test/results/clientnegative/ambiguous_col_unqualified_ref.q.out 
b/ql/src/test/results/clientnegative/ambiguous_col_unqualified_ref.q.out
new file mode 100644
index 00000000000..2a604e3b5d2
--- /dev/null
+++ b/ql/src/test/results/clientnegative/ambiguous_col_unqualified_ref.q.out
@@ -0,0 +1 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in bse
diff --git 
a/ql/src/test/results/clientnegative/cbo_ambiguous_colref_in_gby.q.out 
b/ql/src/test/results/clientnegative/cbo_ambiguous_colref_in_gby.q.out
index c3b7baacdf1..8f04d4e45a4 100644
--- a/ql/src/test/results/clientnegative/cbo_ambiguous_colref_in_gby.q.out
+++ b/ql/src/test/results/clientnegative/cbo_ambiguous_colref_in_gby.q.out
@@ -6,4 +6,4 @@ POSTHOOK: query: create table t1 (a int)
 POSTHOOK: type: CREATETABLE
 POSTHOOK: Output: database:default
 POSTHOOK: Output: default@t1
-FAILED: SemanticException Ambiguous column reference: s.a
+FAILED: SemanticException [Error 10007]: Ambiguous column reference a in s
diff --git a/ql/src/test/results/clientnegative/cte_col_alias_clash.q.out 
b/ql/src/test/results/clientnegative/cte_col_alias_clash.q.out
index 686e3689d3c..475dc7384b7 100644
--- a/ql/src/test/results/clientnegative/cte_col_alias_clash.q.out
+++ b/ql/src/test/results/clientnegative/cte_col_alias_clash.q.out
@@ -6,4 +6,4 @@ POSTHOOK: query: create table t1(int_col int, bigint_col bigint)
 POSTHOOK: type: CREATETABLE
 POSTHOOK: Output: database:default
 POSTHOOK: Output: default@t1
-FAILED: SemanticException Ambiguous column reference: .a
+FAILED: SemanticException [Error 10007]: Ambiguous column reference a in cte1
diff --git 
a/ql/src/test/results/clientpositive/llap/ambiguous_col_noncbo_baseline.q.out 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_noncbo_baseline.q.out
new file mode 100644
index 00000000000..3ab30363d78
--- /dev/null
+++ 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_noncbo_baseline.q.out
@@ -0,0 +1,44 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in t
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in c1
+FAILED: SemanticException [Error 10007]: Ambiguous column reference key in subq
+PREHOOK: query: create table wj3 (k int, v int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@wj3
+POSTHOOK: query: create table wj3 (k int, v int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@wj3
+PREHOOK: query: create table wj4 (k int, w int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@wj4
+POSTHOOK: query: create table wj4 (k int, w int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@wj4
+FAILED: SemanticException [Error 10007]: Ambiguous column reference k in t
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in a
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in sq_1
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in sq_1
+FAILED: SemanticException [Error 10007]: Ambiguous column reference key in a
+PREHOOK: query: create table t1nc (c1 int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t1nc
+POSTHOOK: query: create table t1nc (c1 int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t1nc
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c1 in t
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in bse
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in 
__u1-subquery1
+PREHOOK: query: create table t1gnc (a int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@t1gnc
+POSTHOOK: query: create table t1gnc (a int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@t1gnc
+FAILED: SemanticException [Error 10007]: Ambiguous column reference a in s
diff --git 
a/ql/src/test/results/clientpositive/llap/ambiguous_col_rejected.q.out 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_rejected.q.out
new file mode 100644
index 00000000000..4973d8056e0
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/ambiguous_col_rejected.q.out
@@ -0,0 +1,5 @@
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in tpm
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in t
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in x
+FAILED: SemanticException [Error 10007]: Ambiguous column reference c in z
+FAILED: SemanticException [Error 10007]: Ambiguous column reference a in 
renamed
diff --git 
a/ql/src/test/results/clientpositive/llap/ambiguous_col_tolerated.q.out 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_tolerated.q.out
new file mode 100644
index 00000000000..c0656b21784
--- /dev/null
+++ b/ql/src/test/results/clientpositive/llap/ambiguous_col_tolerated.q.out
@@ -0,0 +1,110 @@
+PREHOOK: query: select 'a' as c, 'b' as c
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select 'a' as c, 'b' as c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: select 'a' as c, 'b' as c order by c
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select 'a' as c, 'b' as c order by c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: select * from (select 'a' as c, 'b' as c) t
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select * from (select 'a' as c, 'b' as c) t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: create table dup_alias_ins (x string, y string)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@dup_alias_ins
+POSTHOOK: query: create table dup_alias_ins (x string, y string)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@dup_alias_ins
+PREHOOK: query: insert into dup_alias_ins select 'a' as c, 'b' as c
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@dup_alias_ins
+POSTHOOK: query: insert into dup_alias_ins select 'a' as c, 'b' as c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@dup_alias_ins
+POSTHOOK: Lineage: dup_alias_ins.x SIMPLE []
+POSTHOOK: Lineage: dup_alias_ins.y SIMPLE []
+PREHOOK: query: select x, y from dup_alias_ins
+PREHOOK: type: QUERY
+PREHOOK: Input: default@dup_alias_ins
+#### A masked pattern was here ####
+POSTHOOK: query: select x, y from dup_alias_ins
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@dup_alias_ins
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: with bse as (select 'a' as c, 'b' as c), renamed(a, b) as 
(select * from bse) select renamed.a from renamed
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: with bse as (select 'a' as c, 'b' as c), renamed(a, b) as 
(select * from bse) select renamed.a from renamed
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a
+PREHOOK: query: select 'a' as c, 'b' as c
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select 'a' as c, 'b' as c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: select 'a' as c, 'b' as c order by c
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select 'a' as c, 'b' as c order by c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: select * from (select 'a' as c, 'b' as c) t
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select * from (select 'a' as c, 'b' as c) t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: insert into dup_alias_ins select 'c' as c, 'd' as c
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+PREHOOK: Output: default@dup_alias_ins
+POSTHOOK: query: insert into dup_alias_ins select 'c' as c, 'd' as c
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+POSTHOOK: Output: default@dup_alias_ins
+POSTHOOK: Lineage: dup_alias_ins.x SIMPLE []
+POSTHOOK: Lineage: dup_alias_ins.y SIMPLE []
+PREHOOK: query: select x, y from dup_alias_ins order by x
+PREHOOK: type: QUERY
+PREHOOK: Input: default@dup_alias_ins
+#### A masked pattern was here ####
+POSTHOOK: query: select x, y from dup_alias_ins order by x
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@dup_alias_ins
+#### A masked pattern was here ####
+a      b
+c      d
diff --git 
a/ql/src/test/results/clientpositive/llap/ambiguous_col_union_distinct_tolerated.q.out
 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_union_distinct_tolerated.q.out
new file mode 100644
index 00000000000..98f54127948
--- /dev/null
+++ 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_union_distinct_tolerated.q.out
@@ -0,0 +1,20 @@
+PREHOOK: query: select 'a' as c, 'b' as c union select 'a', 'b' union select 
'a', 'x'
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select 'a' as c, 'b' as c union select 'a', 'b' union select 
'a', 'x'
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+a      x
+PREHOOK: query: select distinct * from (select 'a' as c, 'b' as c union all 
select 'a', 'b' union all select 'a', 'x') t
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select distinct * from (select 'a' as c, 'b' as c union all 
select 'a', 'b' union all select 'a', 'x') t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+a      x
diff --git 
a/ql/src/test/results/clientpositive/llap/ambiguous_col_unreferenced_tolerated.q.out
 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_unreferenced_tolerated.q.out
new file mode 100644
index 00000000000..dc25bfa8bd0
--- /dev/null
+++ 
b/ql/src/test/results/clientpositive/llap/ambiguous_col_unreferenced_tolerated.q.out
@@ -0,0 +1,101 @@
+PREHOOK: query: select t.d from (select 'a' as c, 'b' as c, 'x' as d) t
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select t.d from (select 'a' as c, 'b' as c, 'x' as d) t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+x
+PREHOOK: query: with c1 as (select 'a' as c, 'b' as c, 'x' as d)
+select d from c1
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: with c1 as (select 'a' as c, 'b' as c, 'x' as d)
+select d from c1
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+x
+PREHOOK: query: select count(1) from (select 'a' as c, 'b' as c) t
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select count(1) from (select 'a' as c, 'b' as c) t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+1
+PREHOOK: query: select count(*) from (select key, key from src) subq
+PREHOOK: type: QUERY
+PREHOOK: Input: default@src
+#### A masked pattern was here ####
+POSTHOOK: query: select count(*) from (select key, key from src) subq
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@src
+#### A masked pattern was here ####
+500
+PREHOOK: query: create table wjt1 (k int, v int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@wjt1
+POSTHOOK: query: create table wjt1 (k int, v int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@wjt1
+PREHOOK: query: create table wjt2 (k int, w int)
+PREHOOK: type: CREATETABLE
+PREHOOK: Output: database:default
+PREHOOK: Output: default@wjt2
+POSTHOOK: query: create table wjt2 (k int, w int)
+POSTHOOK: type: CREATETABLE
+POSTHOOK: Output: database:default
+POSTHOOK: Output: default@wjt2
+PREHOOK: query: select t.v from (select a.*, b.* from wjt1 a join wjt2 b on 
a.k = b.k) t
+PREHOOK: type: QUERY
+PREHOOK: Input: default@wjt1
+PREHOOK: Input: default@wjt2
+#### A masked pattern was here ####
+POSTHOOK: query: select t.v from (select a.*, b.* from wjt1 a join wjt2 b on 
a.k = b.k) t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@wjt1
+POSTHOOK: Input: default@wjt2
+#### A masked pattern was here ####
+PREHOOK: query: select * from (select * from (select 'a' as c, 'b' as c) a) b
+PREHOOK: type: QUERY
+PREHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+POSTHOOK: query: select * from (select * from (select 'a' as c, 'b' as c) a) b
+POSTHOOK: type: QUERY
+POSTHOOK: Input: _dummy_database@_dummy_table
+#### A masked pattern was here ####
+a      b
+PREHOOK: query: select count(*) from src a where exists (select 'x' as c, 'y' 
as c from src b where b.key = a.key)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@src
+#### A masked pattern was here ####
+POSTHOOK: query: select count(*) from src a where exists (select 'x' as c, 'y' 
as c from src b where b.key = a.key)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@src
+#### A masked pattern was here ####
+500
+Warning: Shuffle Join MERGEJOIN[18][tables = [$hdt$_0, $hdt$_1]] in Stage 
'Reducer 2' is a cross product
+PREHOOK: query: select count(*) from src where exists (select 'a' as c, 'b' as 
c from src)
+PREHOOK: type: QUERY
+PREHOOK: Input: default@src
+#### A masked pattern was here ####
+POSTHOOK: query: select count(*) from src where exists (select 'a' as c, 'b' 
as c from src)
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@src
+#### A masked pattern was here ####
+500
+PREHOOK: query: select count(*) from (select value from src group by value 
having exists (select 'x' as c, 'y' as c from src b where b.value = src.value)) 
t
+PREHOOK: type: QUERY
+PREHOOK: Input: default@src
+#### A masked pattern was here ####
+POSTHOOK: query: select count(*) from (select value from src group by value 
having exists (select 'x' as c, 'y' as c from src b where b.value = src.value)) 
t
+POSTHOOK: type: QUERY
+POSTHOOK: Input: default@src
+#### A masked pattern was here ####
+309
diff --git a/ql/src/test/results/clientpositive/llap/cross_prod_3.q.out 
b/ql/src/test/results/clientpositive/llap/cross_prod_3.q.out
index 6e6278f6f74..78fdff96bb5 100644
--- a/ql/src/test/results/clientpositive/llap/cross_prod_3.q.out
+++ b/ql/src/test/results/clientpositive/llap/cross_prod_3.q.out
@@ -30,12 +30,12 @@ POSTHOOK: Output: database:default
 POSTHOOK: Output: default@Y_n0
 POSTHOOK: Lineage: y_n0.key SIMPLE [(src)src.FieldSchema(name:key, 
type:string, comment:default), ]
 POSTHOOK: Lineage: y_n0.value SIMPLE [(src)src.FieldSchema(name:value, 
type:string, comment:default), ]
-PREHOOK: query: explain select * from Y_n0, (select * from X_n2 as A join X_n2 
as B on A.key=B.key) as C where Y_n0.key=C.key
+PREHOOK: query: explain select * from Y_n0, (select A.key, A.value, B.key as 
key2, B.value as value2 from X_n2 as A join X_n2 as B on A.key=B.key) as C 
where Y_n0.key=C.key
 PREHOOK: type: QUERY
 PREHOOK: Input: default@x_n2
 PREHOOK: Input: default@y_n0
 #### A masked pattern was here ####
-POSTHOOK: query: explain select * from Y_n0, (select * from X_n2 as A join 
X_n2 as B on A.key=B.key) as C where Y_n0.key=C.key
+POSTHOOK: query: explain select * from Y_n0, (select A.key, A.value, B.key as 
key2, B.value as value2 from X_n2 as A join X_n2 as B on A.key=B.key) as C 
where Y_n0.key=C.key
 POSTHOOK: type: QUERY
 POSTHOOK: Input: default@x_n2
 POSTHOOK: Input: default@y_n0
diff --git a/ql/src/test/results/clientpositive/llap/limit_join_transpose.q.out 
b/ql/src/test/results/clientpositive/llap/limit_join_transpose.q.out
index e1228b6403b..ad73abc0393 100644
--- a/ql/src/test/results/clientpositive/llap/limit_join_transpose.q.out
+++ b/ql/src/test/results/clientpositive/llap/limit_join_transpose.q.out
@@ -352,7 +352,7 @@ POSTHOOK: Input: default@src
 PREHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -363,7 +363,7 @@ PREHOOK: Input: default@src
 POSTHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -505,7 +505,7 @@ STAGE PLANS:
 
 PREHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -515,7 +515,7 @@ PREHOOK: Input: default@src
 #### A masked pattern was here ####
 POSTHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -527,7 +527,7 @@ POSTHOOK: Input: default@src
 PREHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -538,7 +538,7 @@ PREHOOK: Input: default@src
 POSTHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -693,7 +693,7 @@ STAGE PLANS:
 
 PREHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -703,7 +703,7 @@ PREHOOK: Input: default@src
 #### A masked pattern was here ####
 POSTHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -936,7 +936,7 @@ POSTHOOK: Input: default@src
 PREHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -947,7 +947,7 @@ PREHOOK: Input: default@src
 POSTHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -967,7 +967,7 @@ STAGE PLANS:
 
 PREHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -977,7 +977,7 @@ PREHOOK: Input: default@src
 #### A masked pattern was here ####
 POSTHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1393,7 +1393,7 @@ POSTHOOK: Input: default@src
 PREHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1404,7 +1404,7 @@ PREHOOK: Input: default@src
 POSTHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1564,7 +1564,7 @@ STAGE PLANS:
 
 PREHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1574,7 +1574,7 @@ PREHOOK: Input: default@src
 #### A masked pattern was here ####
 POSTHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1586,7 +1586,7 @@ POSTHOOK: Input: default@src
 PREHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1597,7 +1597,7 @@ PREHOOK: Input: default@src
 POSTHOOK: query: explain
 select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1770,7 +1770,7 @@ STAGE PLANS:
 
 PREHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key
@@ -1780,7 +1780,7 @@ PREHOOK: Input: default@src
 #### A masked pattern was here ####
 POSTHOOK: query: select *
 from src src1 right outer join (
-  select *
+  select src2.key, src2.value, src3.key as key3, src3.value as value3
   from src src2 left outer join src src3
   on src2.value = src3.value) src2
 on src1.key = src2.key

Reply via email to