diff --git a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
index 99e52c5e4ed7..a063e5b8fa9d 100644
--- a/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
+++ b/core/src/main/java/org/apache/calcite/sql/validate/SqlValidatorImpl.java
@@ -4474,6 +4474,21 @@ protected void validateWhereOrOn(
SqlNode condition,
String clause) {
validateNoAggs(aggOrOverOrGroupFinder, condition, clause);
+ // SqlSelect need to expand alias
+ condition.accept(new SqlShuttle() {
+ @Override public @Nullable SqlNode visit(SqlCall call) {
+ call.getOperandList()
+ .stream()
+ .filter(Objects::nonNull)
+ .forEach(node -> node.accept(this));
+ if (call.getKind() == SqlKind.SELECT) {
+ SqlSelect select = (SqlSelect) call;
+ validateHavingClause(select);
+ return select;
+ }
+ return call;
+ }
+ });
inferUnknownTypes(
booleanType,
scope,
diff --git a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
index f7460a661170..fdbaf6e960cb 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlToRelConverterTest.java
@@ -378,6 +378,28 @@ public static void checkActualAndReferenceFiles() {
.withConformance(SqlConformanceEnum.LENIENT).ok();
}
+ /** Test case for
+ * [CALCITE-5486]
+ * SubQuery not support HAVING alias in where condition. */
+ @Test void testHavingAliasInSubQuery1() {
+ final String sql = "select * from emp where sal >\n"
+ + " (select avg(sal) as s"
+ + " from emp having s > 0"
+ + " )";
+ sql(sql).withConformance(SqlConformanceEnum.LENIENT).ok();
+ }
+
+ @Test void testHavingAliasInSubQuery2() {
+ final String sql = "select * from emp e "
+ + "left join dept d "
+ + "on e.deptno = d.deptno "
+ + "and sal >\n"
+ + " (select avg(sal) as s"
+ + " from emp having s > 0"
+ + " )";
+ sql(sql).withConformance(SqlConformanceEnum.LENIENT).ok();
+ }
+
@Test void testAliasInHaving() {
sql("select count(empno) as e from emp having e > 1")
.withConformance(SqlConformanceEnum.LENIENT).ok();
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index 17cc9306af1c..d7ebbcb86af9 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -5709,6 +5709,19 @@ public boolean isBangEqualAllowed() {
.withConformance(lenient).ok();
}
+ /** Test case for
+ * [CALCITE-5486]
+ * SubQuery not support HAVING alias in where condition. */
+ @Test void testHavingAliasInCondition() {
+ sql("select * from emp where sal >\n"
+ + " (select avg(sal) as s"
+ + " from emp having ^s^ > 0"
+ + " )")
+ .fails("Column 'S' not found in any table")
+ .withConformance(SqlConformanceEnum.LENIENT)
+ .ok();
+ }
+
/**
* Tests validation of the ORDER BY clause when DISTINCT is present.
*/
diff --git a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
index b69a9a400c55..169fa596ed6f 100644
--- a/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
+++ b/core/src/test/resources/org/apache/calcite/test/SqlToRelConverterTest.xml
@@ -2598,6 +2598,64 @@ LogicalProject(DEPTNO=[$0])
LogicalAggregate(group=[{0}], agg#0=[SUM($1)], agg#1=[SUM($2)])
LogicalProject(DEPTNO=[$7], $f1=[CASE(SEARCH($7, Sarg[1, 2]), 0, 1)], $f2=[CASE(SEARCH($7, Sarg[3, 4]), 0, 1)])
LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+
+
+
+
+
+ (select avg(sal) as s from emp having s > 0 )]]>
+
+
+ ($5, $9)])
+ LogicalJoin(condition=[true], joinType=[left])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalAggregate(group=[{}], agg#0=[SINGLE_VALUE($0)])
+ LogicalFilter(condition=[>($0, 0)])
+ LogicalAggregate(group=[{}], S=[AVG($0)])
+ LogicalProject(SAL=[$5])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+
+
+
+
+
+ (select avg(sal) as s from emp having s > 0 )]]>
+
+
+ ($5, $9)])
+ LogicalJoin(condition=[true], joinType=[left])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalAggregate(group=[{}], agg#0=[SINGLE_VALUE($0)])
+ LogicalFilter(condition=[>($0, 0)])
+ LogicalAggregate(group=[{}], S=[AVG($0)])
+ LogicalProject(SAL=[$5])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+]]>
+
+
+
+
+
+ (select avg(sal) as s from emp having s > 0 )]]>
+
+
+ ($5, $0))], joinType=[left])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
+ LogicalJoin(condition=[true], joinType=[left])
+ LogicalTableScan(table=[[CATALOG, SALES, DEPT]])
+ LogicalAggregate(group=[{}], agg#0=[SINGLE_VALUE($0)])
+ LogicalFilter(condition=[>($0, 0)])
+ LogicalAggregate(group=[{}], S=[AVG($0)])
+ LogicalProject(SAL=[$5])
+ LogicalTableScan(table=[[CATALOG, SALES, EMP]])
]]>