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 9c731b8..f4956a9 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 @@ -2644,6 +2644,7 @@ private RelNode genSelectLogicalPlan(QB qb, RelNode srcRel, RelNode starSrcRel) ASTNode exprList = selExprList; int startPosn = posn; List tabAliasesForAllProjs = getTabAliases(starRR); + Set colAliases = new HashSet<>(); for (int i = startPosn; i < exprList.getChildCount(); ++i) { // 6.1 child can be EXPR AS ALIAS, or EXPR. @@ -2665,9 +2666,10 @@ private RelNode genSelectLogicalPlan(QB qb, RelNode srcRel, RelNode starSrcRel) // 6.3 Get rid of TOK_SELEXPR expr = (ASTNode) child.getChild(0); String[] colRef = SemanticAnalyzer.getColAlias(child, getAutogenColAliasPrfxLbl(), inputRR, - autogenColAliasPrfxIncludeFuncName(), i); + autogenColAliasPrfxIncludeFuncName(), i, colAliases); tabAlias = colRef[0]; colAlias = colRef[1]; + colAliases.add(colAlias); // 6.4 Build ExprNode corresponding to colums if (expr.getType() == HiveParser.TOK_ALLCOLREF) { @@ -2713,10 +2715,6 @@ private RelNode genSelectLogicalPlan(QB qb, RelNode srcRel, RelNode starSrcRel) // We allow stateful functions in the SELECT list (but nowhere else) tcCtx.setAllowStatefulFunctions(true); ExprNodeDesc exp = genExprNodeDesc(expr, inputRR, tcCtx); - String recommended = recommendName(exp, colAlias); - if (recommended != null && out_rwsch.get(null, recommended) == null) { - colAlias = recommended; - } col_list.add(exp); ColumnInfo colInfo = new ColumnInfo(SemanticAnalyzer.getColumnInternalName(pos), 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 4bec228..3513acc 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 @@ -3497,7 +3497,7 @@ public static int setBit(int bitmap, int bitIdx) { } static String[] getColAlias(ASTNode selExpr, String defaultName, - RowResolver inputRR, boolean includeFuncName, int colNum) { + RowResolver inputRR, boolean includeFuncName, int colNum, Set colAliases) { String colAlias = null; String tabAlias = null; String[] colRef = new String[2]; @@ -3535,6 +3535,9 @@ public static int setBit(int bitmap, int bitIdx) { ASTNode col = (ASTNode) root.getChild(1); if (col.getType() == HiveParser.Identifier) { colAlias = unescapeIdentifier(col.getText()); + colRef[0] = tabAlias; + colRef[1] = colAlias; + return colRef; } } @@ -3564,7 +3567,15 @@ public static int setBit(int bitmap, int bitIdx) { } colRef[0] = tabAlias; - colRef[1] = colAlias; + int index = 1; + String newColAlias = colAlias; + if (colAliases != null) { + while (colAliases.contains(newColAlias)) { + // This means that the derived colAlias collides with existing ones. + newColAlias = colAlias + "_" + (index++); + } + } + colRef[1] = newColAlias; return colRef; } @@ -3758,7 +3769,7 @@ static boolean isRegex(String pattern, HiveConf conf) { // Get rid of TOK_SELEXPR expr = (ASTNode) child.getChild(0); String[] colRef = getColAlias(child, autogenColAliasPrfxLbl, inputRR, - autogenColAliasPrfxIncludeFuncName, i); + autogenColAliasPrfxIncludeFuncName, i, colAliases); tabAlias = colRef[0]; colAlias = colRef[1]; if (hasAsClause) { @@ -3768,6 +3779,7 @@ static boolean isRegex(String pattern, HiveConf conf) { } exprs[i] = expr; aliases[i] = new String[] {tabAlias, colAlias}; + colAliases.add(colAlias); hasAsClauses[i] = hasAsClause; colAliases.add(colAlias); } @@ -3812,11 +3824,6 @@ static boolean isRegex(String pattern, HiveConf conf) { tcCtx.setAllowStatefulFunctions(true); tcCtx.setAllowDistinctFunctions(false); ExprNodeDesc exp = genExprNodeDesc(expr, inputRR, tcCtx); - String recommended = recommendName(exp, colAlias); - if (recommended != null && !colAliases.contains(recommended) && - out_rwsch.get(null, recommended) == null) { - colAlias = recommended; - } col_list.add(exp); ColumnInfo colInfo = new ColumnInfo(getColumnInternalName(pos), @@ -12094,7 +12101,7 @@ private Operator genReduceSinkPlanForWindowing(WindowingSpec spec, alias = aliasNode.getText(); } else { - String[] tabColAlias = getColAlias(selExpr, null, null, true, -1); + String[] tabColAlias = getColAlias(selExpr, null, null, true, -1, null); alias = tabColAlias[1]; } WindowExpressionSpec exprSpec = new WindowExpressionSpec(); diff --git a/ql/src/test/queries/clientpositive/duplicate_column_names.q b/ql/src/test/queries/clientpositive/duplicate_column_names.q new file mode 100644 index 0000000..5dfc296 --- /dev/null +++ b/ql/src/test/queries/clientpositive/duplicate_column_names.q @@ -0,0 +1,13 @@ +create table t as select key as `_c1`, count(key) from src group by key; + +describe t; + +set hive.cbo.enable=false; + +drop table t; + +create table t as select key as `_c1`, count(key) from src group by key; + +describe t; + + diff --git a/ql/src/test/results/clientpositive/duplicate_column_names.q.out b/ql/src/test/results/clientpositive/duplicate_column_names.q.out new file mode 100644 index 0000000..eb0d13c --- /dev/null +++ b/ql/src/test/results/clientpositive/duplicate_column_names.q.out @@ -0,0 +1,44 @@ +PREHOOK: query: create table t as select key as `_c1`, count(key) from src group by key +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: default@src +PREHOOK: Output: database:default +PREHOOK: Output: default@t +POSTHOOK: query: create table t as select key as `_c1`, count(key) from src group by key +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: default@src +POSTHOOK: Output: database:default +POSTHOOK: Output: default@t +PREHOOK: query: describe t +PREHOOK: type: DESCTABLE +PREHOOK: Input: default@t +POSTHOOK: query: describe t +POSTHOOK: type: DESCTABLE +POSTHOOK: Input: default@t +c1 string +c1_1 bigint +PREHOOK: query: drop table t +PREHOOK: type: DROPTABLE +PREHOOK: Input: default@t +PREHOOK: Output: default@t +POSTHOOK: query: drop table t +POSTHOOK: type: DROPTABLE +POSTHOOK: Input: default@t +POSTHOOK: Output: default@t +PREHOOK: query: create table t as select key as `_c1`, count(key) from src group by key +PREHOOK: type: CREATETABLE_AS_SELECT +PREHOOK: Input: default@src +PREHOOK: Output: database:default +PREHOOK: Output: default@t +POSTHOOK: query: create table t as select key as `_c1`, count(key) from src group by key +POSTHOOK: type: CREATETABLE_AS_SELECT +POSTHOOK: Input: default@src +POSTHOOK: Output: database:default +POSTHOOK: Output: default@t +PREHOOK: query: describe t +PREHOOK: type: DESCTABLE +PREHOOK: Input: default@t +POSTHOOK: query: describe t +POSTHOOK: type: DESCTABLE +POSTHOOK: Input: default@t +_c1 string +_c1_1 bigint