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