diff --git a/planner/core/logical_plan_builder.go b/planner/core/logical_plan_builder.go index df1c0fba28b2d..f61c3c86a378b 100644 --- a/planner/core/logical_plan_builder.go +++ b/planner/core/logical_plan_builder.go @@ -1431,7 +1431,6 @@ type havingWindowAndOrderbyExprResolver struct { inWindowFunc bool inWindowSpec bool inExpr bool - orderBy bool err error p LogicalPlan selectFields []*ast.SelectField @@ -1523,10 +1522,10 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o a.inWindowSpec = false case *ast.ColumnNameExpr: resolveFieldsFirst := true - if a.inAggFunc || a.inWindowFunc || a.inWindowSpec || (a.orderBy && a.inExpr) || a.curClause == fieldList { + if a.inAggFunc || a.inWindowFunc || a.inWindowSpec || (a.curClause == orderByClause && a.inExpr) || a.curClause == fieldList { resolveFieldsFirst = false } - if !a.inAggFunc && !a.orderBy { + if !a.inAggFunc && a.curClause != orderByClause { for _, item := range a.gbyItems { if col, ok := item.Expr.(*ast.ColumnNameExpr); ok && (colMatch(v.Name, col.Name) || colMatch(col.Name, v.Name)) { @@ -1546,8 +1545,22 @@ func (a *havingWindowAndOrderbyExprResolver) Leave(n ast.Node) (node ast.Node, o return node, false } if index == -1 { - if a.orderBy { + if a.curClause == orderByClause { index, a.err = a.resolveFromPlan(v, a.p) + } else if a.curClause == havingClause && v.Name.Table.L != "" { + // For SQLs like: + // select a from t b having b.a; + index, a.err = a.resolveFromPlan(v, a.p) + if a.err != nil { + return node, false + } + if index != -1 { + // For SQLs like: + // select a+1 from t having t.a; + newV := v + newV.Name = &ast.ColumnName{Name: v.Name.Name} + index, a.err = resolveFromSelectFields(newV, a.selectFields, true) + } } else { index, a.err = resolveFromSelectFields(v, a.selectFields, true) } @@ -1619,7 +1632,6 @@ func (b *PlanBuilder) resolveHavingAndOrderBy(sel *ast.SelectStmt, p LogicalPlan } havingAggMapper := extractor.aggMapper extractor.aggMapper = make(map[*ast.AggregateFuncExpr]int) - extractor.orderBy = true extractor.inExpr = false // Extract agg funcs from order by clause. if sel.OrderBy != nil { diff --git a/planner/core/logical_plan_test.go b/planner/core/logical_plan_test.go index 08b380d109715..c32dc29fd3220 100644 --- a/planner/core/logical_plan_test.go +++ b/planner/core/logical_plan_test.go @@ -770,6 +770,22 @@ func (s *testPlanSuite) TestValidate(c *C) { sql: "select concat(c_str, d_str) from t group by `concat(c_str,d_str)`", err: ErrUnknownColumn, }, + { + sql: "select a from t b having b.a", + err: nil, + }, + { + sql: "select b.a from t b having b.a", + err: nil, + }, + { + sql: "select b.a from t b having a", + err: nil, + }, + { + sql: "select a+1 from t having t.a", + err: ErrUnknownColumn, + }, } ctx := context.Background()