Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions enginetest/queries/queries.go
Original file line number Diff line number Diff line change
Expand Up @@ -8904,6 +8904,12 @@ from typestable`,
{0},
},
},
{
Query: "select 0 as col1, 1 as col2, 2 as col2 group by col2 having col2 = 1",
Expected: []sql.Row{
{0, 1, 2},
},
},
}

var KeylessQueries = []QueryTest{
Expand Down Expand Up @@ -9117,6 +9123,13 @@ FROM mytable;`,
Query: "select TABLE_NAME, IS_UPDATABLE from information_schema.views where table_schema = 'mydb'",
Expected: []sql.Row{{"myview1", "YES"}, {"myview2", "YES"}, {"myview3", "NO"}, {"myview4", "NO"}, {"myview5", "YES"}},
},
{
// This should through a duplicate column error
Query: "select * from (select 0 as col1, 1 as col2, 2 as col2 group by col2 having col2 = 1) sq;",
Expected: []sql.Row{
{0, 1, 2},
},
},
}

var VersionedQueries = []QueryTest{
Expand Down
17 changes: 17 additions & 0 deletions enginetest/queries/query_plans.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

33 changes: 33 additions & 0 deletions sql/analyzer/fix_exec_indexes.go
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,8 @@ type idxScope struct {
children []sql.Node
expressions []sql.Expression
checks sql.CheckConstraints
isHaving bool
isGroupBy bool
}

func (s *idxScope) addSchema(sch sql.Schema) {
Expand Down Expand Up @@ -107,6 +109,16 @@ func unqualify(s string) string {
}

func (s *idxScope) getIdx(n string) (int, bool) {
// Special case for group by and having
if s.isGroupBy || s.isHaving {
for i := 0; i < len(s.columns); i++ {
if strings.EqualFold(n, s.columns[i]) {
return i, true
}
}
return -1, false
}

// We match the column closet to our current scope. We have already
// resolved columns, so there will be no in-scope collisions.
if isQualified(n) {
Expand Down Expand Up @@ -364,6 +376,21 @@ func (s *idxScope) visitSelf(n sql.Node) error {
newCheck.Expr = newE
s.checks = append(s.checks, &newCheck)
}
case *plan.Having:
newScope := &idxScope{}
for _, scope := range s.parentScopes {
newScope.addScope(scope)
}
for _, scope := range s.childScopes {
newScope.addScope(scope)
}
newScope.isHaving = true
defer func() {
newScope.isHaving = false
}()
for _, e := range n.Expressions() {
s.expressions = append(s.expressions, fixExprToScope(e, newScope))
}
default:
if ne, ok := n.(sql.Expressioner); ok {
scope := append(s.parentScopes, s.childScopes...)
Expand Down Expand Up @@ -433,6 +460,12 @@ func fixExprToScope(e sql.Expression, scopes ...*idxScope) sql.Expression {
newScope := &idxScope{}
for _, s := range scopes {
newScope.addScope(s)
if s.isGroupBy {
newScope.isGroupBy = true
}
if s.isHaving {
newScope.isHaving = true
}
}
ret, _, _ := transform.Expr(e, func(e sql.Expression) (sql.Expression, transform.TreeIdentity, error) {
switch e := e.(type) {
Expand Down
19 changes: 19 additions & 0 deletions sql/planbuilder/aggregates.go
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,15 @@ func (b *Builder) buildGroupingCols(fromScope, projScope *scope, groupby ast.Gro
fromScope.initGroupBy()
}
g := fromScope.groupBy

fromScope.isGroupBy = true
projScope.isGroupBy = true

defer func() {
fromScope.isGroupBy = false
projScope.isGroupBy = false
}()

for _, e := range groupby {
var col scopeColumn
switch e := e.(type) {
Expand Down Expand Up @@ -709,6 +718,14 @@ func (b *Builder) analyzeHaving(fromScope, projScope *scope, having *ast.Where)
return
}

projScope.isHaving = true
fromScope.isHaving = true

defer func() {
projScope.isHaving = false
fromScope.isHaving = false
}()

ast.Walk(func(node ast.SQLNode) (bool, error) {
switch n := node.(type) {
case *ast.Subquery:
Expand All @@ -731,6 +748,7 @@ func (b *Builder) analyzeHaving(fromScope, projScope *scope, having *ast.Where)
// references projection alias
break
}

c, ok = fromScope.resolveColumn(dbName, tblName, colName, true)
if !ok {
err := sql.ErrColumnNotFound.New(n.Name)
Expand Down Expand Up @@ -782,6 +800,7 @@ func (b *Builder) buildHaving(fromScope, projScope, outScope *scope, having *ast
}
}
havingScope.groupBy = fromScope.groupBy
havingScope.isHaving = true
h := b.buildScalar(havingScope, having.Expr)
outScope.node = plan.NewHaving(h, outScope.node)
return
Expand Down
7 changes: 7 additions & 0 deletions sql/planbuilder/scope.go
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,9 @@ type scope struct {
// exprs collects unique expression ids for reference
exprs map[string]columnId
proc *procCtx
// ignore ambiguous column errors
isGroupBy bool
isHaving bool
}

func (s *scope) resolveColumn(db, table, col string, checkParent bool) (scopeColumn, bool) {
Expand Down Expand Up @@ -105,6 +108,10 @@ func (s *scope) resolveColumn(db, table, col string, checkParent bool) (scopeCol
}
found = c
foundCand = true

if s.isGroupBy || s.isHaving {
break
}
}
}
if foundCand {
Expand Down