From 61723d605346ebdc27f4e8b28d7b1a3596d2b147 Mon Sep 17 00:00:00 2001 From: zhyass <34016424+zhyass@users.noreply.github.com> Date: Wed, 30 Oct 2019 12:22:07 +0800 Subject: [PATCH] planner: refactor the filterTuple #480 [summary] merge the filterTuple and joinTuple. [test case] src/planner/from_test.go src/planner/select_plan_test.go [patch codecov] 96.9% --- src/planner/expr.go | 57 ++++++++++-------------- src/planner/from.go | 8 ++-- src/planner/from_test.go | 4 +- src/planner/join_node.go | 78 ++++++++++++++++----------------- src/planner/merge_node.go | 10 ++--- src/planner/plan_node.go | 8 ++-- src/planner/select_plan_test.go | 2 +- 7 files changed, 78 insertions(+), 89 deletions(-) diff --git a/src/planner/expr.go b/src/planner/expr.go index db1c8e02..2f9739b9 100644 --- a/src/planner/expr.go +++ b/src/planner/expr.go @@ -487,46 +487,35 @@ func convertToLeftJoin(joinExpr *sqlparser.JoinTableExpr) { joinExpr.Join = sqlparser.LeftJoinStr } -type filterTuple struct { +type exprInfo struct { // filter expr. expr sqlparser.Expr // referred tables. referTables []string // colname in the filter expr. - col *sqlparser.ColName + cols []*sqlparser.ColName // val in the filter expr. vals []*sqlparser.SQLVal } -type joinTuple struct { - // join expr. - expr *sqlparser.ComparisonExpr - // referred tables. - referTables []string - left, right *sqlparser.ColName -} - // parserWhereOrJoinExprs parser exprs in where or join on conditions. // eg: 't1.a=t2.a and t1.b=2'. -// t1.a=t2.a paser in joinTuple. -// t1.b=2 paser in filterTuple, t1.b col, 2 val. -func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) ([]joinTuple, []filterTuple, error) { +// t1.a=t2.a paser in joins. +// t1.b=2 paser in wheres, t1.b col, 2 val. +func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) ([]exprInfo, []exprInfo, error) { filters := splitAndExpression(nil, exprs) - var joins []joinTuple - var wheres []filterTuple + var joins, wheres []exprInfo for _, filter := range filters { - var col *sqlparser.ColName + var cols []*sqlparser.ColName var vals []*sqlparser.SQLVal - count := 0 filter = skipParenthesis(filter) filter = convertOrToIn(filter) referTables := make([]string, 0, 4) err := sqlparser.Walk(func(node sqlparser.SQLNode) (kontinue bool, err error) { switch node := node.(type) { case *sqlparser.ColName: - count++ - col = node + cols = append(cols, node) tableName := node.Qualifier.Name.String() if tableName == "" { if len(tbInfos) == 1 { @@ -536,7 +525,7 @@ func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) } } else { if _, ok := tbInfos[tableName]; !ok { - return false, errors.Errorf("unsupported: unknown.table.'%s'.in.clause", tableName) + return false, errors.Errorf("unsupported: unknown.column.'%s.%s'.in.clause", tableName, node.Name.String()) } } @@ -546,6 +535,8 @@ func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) } } referTables = append(referTables, tableName) + case *sqlparser.Subquery: + return false, errors.New("unsupported: subqueries.in.select") } return true, nil }, filter) @@ -553,9 +544,6 @@ func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) return nil, nil, err } - if count != 1 { - col = nil - } condition, ok := filter.(*sqlparser.ComparisonExpr) if ok { lc, lok := condition.Left.(*sqlparser.ColName) @@ -563,7 +551,7 @@ func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) switch condition.Operator { case sqlparser.EqualStr: if lok && rok && lc.Qualifier != rc.Qualifier { - tuple := joinTuple{condition, referTables, lc, rc} + tuple := exprInfo{condition, referTables, []*sqlparser.ColName{lc, rc}, nil} joins = append(joins, tuple) continue } @@ -576,6 +564,7 @@ func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) if rok { if sqlVal, ok := condition.Left.(*sqlparser.SQLVal); ok { vals = append(vals, sqlVal) + condition.Left, condition.Right = condition.Right, condition.Left } } case sqlparser.InStr: @@ -598,18 +587,18 @@ func parserWhereOrJoinExprs(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) } } } - tuple := filterTuple{filter, referTables, col, vals} + tuple := exprInfo{filter, referTables, cols, vals} wheres = append(wheres, tuple) } return joins, wheres, nil } -// checkJoinOn use to check the join on conditions, according to lpn|rpn to determine join.left|right. +// checkJoinOn use to check the join on conditions, according to lpn|rpn to determine join.cols[0]|cols[1]. // eg: select * from t1 join t2 on t1.a=t2.a join t3 on t2.b=t1.b. 't2.b=t1.b' is forbidden. -func checkJoinOn(lpn, rpn SelectNode, join joinTuple) (joinTuple, error) { - lt := join.left.Qualifier.Name.String() - rt := join.right.Qualifier.Name.String() +func checkJoinOn(lpn, rpn PlanNode, join exprInfo) (exprInfo, error) { + lt := join.cols[0].Qualifier.Name.String() + rt := join.cols[1].Qualifier.Name.String() if _, ok := lpn.getReferTables()[lt]; ok { if _, ok := rpn.getReferTables()[rt]; !ok { return join, errors.New("unsupported: join.on.condition.should.cross.left-right.tables") @@ -618,7 +607,7 @@ func checkJoinOn(lpn, rpn SelectNode, join joinTuple) (joinTuple, error) { if _, ok := lpn.getReferTables()[rt]; !ok { return join, errors.New("unsupported: join.on.condition.should.cross.left-right.tables") } - join.left, join.right = join.right, join.left + join.cols[0], join.cols[1] = join.cols[1], join.cols[0] } return join, nil } @@ -737,9 +726,9 @@ func checkDistinct(node *sqlparser.Select, groups, fields []selectTuple, router // parserHaving used to check the having exprs and parser into tuples. // unsupport: `select t2.id as tmp, t1.id from t2,t1 having tmp=1`. -func parserHaving(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) ([]filterTuple, error) { +func parserHaving(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) ([]exprInfo, error) { filters := splitAndExpression(nil, exprs) - var tuples []filterTuple + var tuples []exprInfo for _, filter := range filters { filter = skipParenthesis(filter) @@ -778,7 +767,7 @@ func parserHaving(exprs sqlparser.Expr, tbInfos map[string]*tableInfo) ([]filter return nil, err } - tuple := filterTuple{filter, referTables, nil, nil} + tuple := exprInfo{filter, referTables, nil, nil} tuples = append(tuples, tuple) } @@ -792,7 +781,7 @@ type nullExpr struct { } // checkIsWithNull used to check whether `tb.col is null` or `tb.col<=> null`. -func checkIsWithNull(filter filterTuple, tbInfos map[string]*tableInfo) (bool, nullExpr) { +func checkIsWithNull(filter exprInfo, tbInfos map[string]*tableInfo) (bool, nullExpr) { if !checkTbInNode(filter.referTables, tbInfos) { return false, nullExpr{} } diff --git a/src/planner/from.go b/src/planner/from.go index 4fcbe38a..48d175e8 100644 --- a/src/planner/from.go +++ b/src/planner/from.go @@ -161,8 +161,8 @@ func scanJoinTableExpr(log *xlog.Log, router *router.Router, database string, jo // If can be merged, left and right merge into one MergeNode. // else build a JoinNode, the two nodes become new joinnode's Left and Right. func join(log *xlog.Log, lpn, rpn SelectNode, joinExpr *sqlparser.JoinTableExpr, router *router.Router) (SelectNode, error) { - var joinOn []joinTuple - var otherJoinOn []filterTuple + var joinOn []exprInfo + var otherJoinOn []exprInfo var err error referTables := make(map[string]*tableInfo) @@ -217,7 +217,7 @@ func join(log *xlog.Log, lpn, rpn SelectNode, joinExpr *sqlparser.JoinTableExpr, } // if join on condition's cols are both shardkey, and the tables have same shards. for _, jt := range joinOn { - if isSameShard(lmn.referTables, rmn.referTables, jt.left, jt.right) { + if isSameShard(lmn.referTables, rmn.referTables, jt.cols[0], jt.cols[1]) { return mergeRoutes(lmn, rmn, joinExpr, otherJoinOn) } } @@ -235,7 +235,7 @@ func join(log *xlog.Log, lpn, rpn SelectNode, joinExpr *sqlparser.JoinTableExpr, } // mergeRoutes merges two MergeNode. -func mergeRoutes(lmn, rmn *MergeNode, joinExpr *sqlparser.JoinTableExpr, otherJoinOn []filterTuple) (*MergeNode, error) { +func mergeRoutes(lmn, rmn *MergeNode, joinExpr *sqlparser.JoinTableExpr, otherJoinOn []exprInfo) (*MergeNode, error) { var err error lSel := lmn.Sel.(*sqlparser.Select) rSel := rmn.Sel.(*sqlparser.Select) diff --git a/src/planner/from_test.go b/src/planner/from_test.go index 2b2b944c..10a4bf77 100644 --- a/src/planner/from_test.go +++ b/src/planner/from_test.go @@ -374,8 +374,8 @@ func TestScanTableExprsError(t *testing.T) { "unsupported: subquery.in.select", "unsupported: join.type:natural join", "unsupported: unknown.column.'id'.in.clause", - "unsupported: unknown.table.'C'.in.clause", - "unsupported: unknown.table.'C'.in.clause", + "unsupported: unknown.column.'C.id'.in.clause", + "unsupported: unknown.column.'C.id'.in.clause", "hash.unsupported.key.type:[3]", "hash.unsupported.key.type:[3]", "Table 'C' doesn't exist (errno 1146) (sqlstate 42S02)", diff --git a/src/planner/join_node.go b/src/planner/join_node.go index 09fd196c..0040af7c 100644 --- a/src/planner/join_node.go +++ b/src/planner/join_node.go @@ -77,7 +77,7 @@ type JoinNode struct { // the returned result fields. fields []selectTuple // join on condition tuples. - joinOn []joinTuple + joinOn []exprInfo // eg: from t1 join t2 on t1.a=t2.b, 't1.a' put in LeftKeys, 't2.a' in RightKeys. LeftKeys, RightKeys []JoinKey // eg: t1 join t2 on t1.a>t2.a, 't1.a>t2.a' parser into CmpFilter. @@ -88,7 +88,7 @@ type JoinNode struct { * parser into otherFilter, else into joinOn. '1=1' parser into noTableFilter. 't2.b>2' into * tableFilter. 't2.str is null' into rightNull. */ - tableFilter, otherFilter []filterTuple + tableFilter, otherFilter []exprInfo noTableFilter []sqlparser.Expr otherJoinOn *otherJoin rightNull []nullExpr @@ -104,7 +104,7 @@ type JoinNode struct { // eg: select * from t1 join t2 on t1.a=t2.a where t1.a=1 // `t1.a` in LeftKeys, `t1.a=1` in tableFilter. in the map, // key is 0(index is 0), value is tableFilter(`t1.a=1`). - keyFilters map[int][]filterTuple + keyFilters map[int][]exprInfo // isHint defines whether has /*+nested+*/. isHint bool order int @@ -115,7 +115,7 @@ type JoinNode struct { // newJoinNode used to create JoinNode. func newJoinNode(log *xlog.Log, Left, Right SelectNode, router *router.Router, joinExpr *sqlparser.JoinTableExpr, - joinOn []joinTuple, referTables map[string]*tableInfo) *JoinNode { + joinOn []exprInfo, referTables map[string]*tableInfo) *JoinNode { isLeftJoin := false if joinExpr != nil && joinExpr.Join == sqlparser.LeftJoinStr { isLeftJoin = true @@ -127,7 +127,7 @@ func newJoinNode(log *xlog.Log, Left, Right SelectNode, router *router.Router, j router: router, joinExpr: joinExpr, joinOn: joinOn, - keyFilters: make(map[int][]filterTuple), + keyFilters: make(map[int][]exprInfo), Vars: make(map[string]int), referTables: referTables, IsLeftJoin: isLeftJoin, @@ -151,7 +151,7 @@ func (j *JoinNode) setParenthese(hasParen bool) { } // pushFilter used to push the filters. -func (j *JoinNode) pushFilter(filters []filterTuple) error { +func (j *JoinNode) pushFilter(filters []exprInfo) error { var err error rightTbs := j.Right.getReferTables() for _, filter := range filters { @@ -169,12 +169,12 @@ func (j *JoinNode) pushFilter(filters []filterTuple) error { if len(filter.referTables) == 1 { tb := filter.referTables[0] tbInfo := j.referTables[tb] - if filter.col == nil { + if len(filter.cols) != 1 { tbInfo.parent.setWhereFilter(filter) } else { j.tableFilter = append(j.tableFilter, filter) if len(filter.vals) > 0 && tbInfo.shardKey != "" { - if nameMatch(filter.col, tb, tbInfo.shardKey) { + if nameMatch(filter.cols[0], tb, tbInfo.shardKey) { for _, val := range filter.vals { if err = getIndex(j.router, tbInfo, val); err != nil { return err @@ -215,7 +215,7 @@ func (j *JoinNode) setParent(p SelectNode) { } // setWhereFilter set the otherFilter. -func (j *JoinNode) setWhereFilter(filter filterTuple) { +func (j *JoinNode) setWhereFilter(filter exprInfo) { j.otherFilter = append(j.otherFilter, filter) } @@ -233,11 +233,11 @@ type otherJoin struct { // filter belong to the left node. left []selectTuple // filter belong to the right node. - right, others []filterTuple + right, others []exprInfo } // setOtherJoin use to process the otherjoinon. -func (j *JoinNode) setOtherJoin(filters []filterTuple) { +func (j *JoinNode) setOtherJoin(filters []exprInfo) { j.otherJoinOn = &otherJoin{} i := 0 for _, filter := range filters { @@ -326,7 +326,7 @@ func (j *JoinNode) pushOtherJoin(idx *int) error { // pushEqualCmpr used to push the equal Comparison type filters. // eg: 'select * from t1, t2 where t1.a=t2.a and t1.b=2'. // 't1.a=t2.a' is the 'join' type filters. -func (j *JoinNode) pushEqualCmpr(joins []joinTuple) SelectNode { +func (j *JoinNode) pushEqualCmpr(joins []exprInfo) SelectNode { for i, joinFilter := range joins { var parent SelectNode ltb := j.referTables[joinFilter.referTables[0]] @@ -340,7 +340,7 @@ func (j *JoinNode) pushEqualCmpr(joins []joinTuple) SelectNode { join, _ := checkJoinOn(node.Left, node.Right, joinFilter) if lmn, ok := node.Left.(*MergeNode); ok { if rmn, ok := node.Right.(*MergeNode); ok { - if isSameShard(lmn.referTables, rmn.referTables, join.left, join.right) { + if isSameShard(lmn.referTables, rmn.referTables, join.cols[0], join.cols[1]) { mn, _ := mergeRoutes(lmn, rmn, node.joinExpr, nil) mn.setParent(node.parent) mn.setParenthese(node.hasParen) @@ -376,7 +376,7 @@ func (j *JoinNode) pushEqualCmpr(joins []joinTuple) SelectNode { } } if node.IsLeftJoin { - node.setWhereFilter(filterTuple{expr: join.expr, referTables: join.referTables}) + node.setWhereFilter(exprInfo{expr: join.expr, referTables: join.referTables}) } else { node.joinOn = append(node.joinOn, join) if node.joinExpr != nil { @@ -443,19 +443,19 @@ func (j *JoinNode) calcRoute() (SelectNode, error) { // eg: select t1.a,t2.a from t1 join t2 on t1.a=t2.a where t1.a=1; // push: select t1.a from t1 where t1.a=1 order by t1.a asc; // select t2.a from t2 where t2.a=1 order by t2.a asc; -func (j *JoinNode) buildKeyFilter(filter filterTuple, isFind bool) bool { - table := filter.col.Qualifier.Name.String() - field := filter.col.Name.String() +func (j *JoinNode) buildKeyFilter(filter exprInfo, isFind bool) bool { + table := filter.cols[0].Qualifier.Name.String() + field := filter.cols[0].Name.String() find := false if _, ok := j.Left.getReferTables()[filter.referTables[0]]; ok { for i, join := range j.joinOn { - lt := join.left.Qualifier.Name.String() - lc := join.left.Name.String() + lt := join.cols[0].Qualifier.Name.String() + lc := join.cols[0].Name.String() if lt == table && lc == field { j.keyFilters[i] = append(j.keyFilters[i], filter) if len(filter.vals) > 0 { - rt := join.right.Qualifier.Name.String() - rc := join.right.Name.String() + rt := join.cols[1].Qualifier.Name.String() + rc := join.cols[1].Name.String() tbInfo := j.referTables[rt] if tbInfo.shardKey == rc { for _, val := range filter.vals { @@ -474,13 +474,13 @@ func (j *JoinNode) buildKeyFilter(filter filterTuple, isFind bool) bool { } } else { for i, join := range j.joinOn { - rt := join.right.Qualifier.Name.String() - rc := join.right.Name.String() + rt := join.cols[1].Qualifier.Name.String() + rc := join.cols[1].Name.String() if rt == table && rc == field { j.keyFilters[i] = append(j.keyFilters[i], filter) if len(filter.vals) > 0 { - lt := join.left.Qualifier.Name.String() - lc := join.left.Name.String() + lt := join.cols[0].Qualifier.Name.String() + lc := join.cols[0].Name.String() tbInfo := j.referTables[lt] if tbInfo.shardKey == lc { for _, val := range filter.vals { @@ -565,7 +565,7 @@ func (j *JoinNode) pushNullExprs(idx *int) error { } // pushOtherFilters used to push otherFilter. -func (j *JoinNode) pushOtherFilters(filters []filterTuple, idx *int, isOtherJoin bool) error { +func (j *JoinNode) pushOtherFilters(filters []exprInfo, idx *int, isOtherJoin bool) error { for _, filter := range filters { var err error var lidx, ridx int @@ -725,8 +725,8 @@ func (j *JoinNode) handleJoinOn() { for _, join := range j.joinOn { var leftKey, rightKey JoinKey if j.isHint { - lt := join.left.Qualifier.Name.String() - rt := join.right.Qualifier.Name.String() + lt := join.cols[0].Qualifier.Name.String() + rt := join.cols[1].Qualifier.Name.String() ltb := j.referTables[lt] rtb := j.referTables[rt] m := ltb.parent @@ -734,15 +734,15 @@ func (j *JoinNode) handleJoinOn() { m = rtb.parent } m.addWhere(join.expr) - leftKey = JoinKey{Field: join.left.Name.String(), + leftKey = JoinKey{Field: join.cols[0].Name.String(), Table: lt, } - rightKey = JoinKey{Field: join.right.Name.String(), + rightKey = JoinKey{Field: join.cols[1].Name.String(), Table: rt, } } else { - leftKey = j.buildOrderBy(join.left, j.Left, nil) - rightKey = j.buildOrderBy(join.right, j.Right, nil) + leftKey = j.buildOrderBy(join.cols[0], j.Left, nil) + rightKey = j.buildOrderBy(join.cols[1], j.Right, nil) } j.LeftKeys = append(j.LeftKeys, leftKey) j.RightKeys = append(j.RightKeys, rightKey) @@ -803,11 +803,11 @@ func (j *JoinNode) buildOrderBy(expr sqlparser.Expr, node SelectNode, idx *int) } // pushHaving used to push having exprs. -func (j *JoinNode) pushHaving(havings []filterTuple) error { +func (j *JoinNode) pushHaving(havings []exprInfo) error { for _, filter := range havings { if len(filter.referTables) == 0 { - j.Left.pushHaving([]filterTuple{filter}) - j.Right.pushHaving([]filterTuple{filter}) + j.Left.pushHaving([]exprInfo{filter}) + j.Right.pushHaving([]exprInfo{filter}) } else if len(filter.referTables) == 1 { tbInfo := j.referTables[filter.referTables[0]] tbInfo.parent.addHaving(filter.expr) @@ -911,8 +911,8 @@ func (j *JoinNode) buildQuery(tbInfos map[string]*tableInfo) { field := j.RightKeys[i].Field tbInfo := j.referTables[table] for _, filter := range filters { - filter.col.Qualifier.Name = sqlparser.NewTableIdent(table) - filter.col.Name = sqlparser.NewColIdent(field) + filter.cols[0].Qualifier.Name = sqlparser.NewTableIdent(table) + filter.cols[0].Name = sqlparser.NewColIdent(field) tbInfo.parent.filters[filter.expr] = 0 } } @@ -924,8 +924,8 @@ func (j *JoinNode) buildQuery(tbInfos map[string]*tableInfo) { field := j.LeftKeys[i].Field tbInfo := j.referTables[table] for _, filter := range filters { - filter.col.Qualifier.Name = sqlparser.NewTableIdent(table) - filter.col.Name = sqlparser.NewColIdent(field) + filter.cols[0].Qualifier.Name = sqlparser.NewTableIdent(table) + filter.cols[0].Name = sqlparser.NewColIdent(field) tbInfo.parent.filters[filter.expr] = 0 } } diff --git a/src/planner/merge_node.go b/src/planner/merge_node.go index 4ed07ca9..7535daee 100644 --- a/src/planner/merge_node.go +++ b/src/planner/merge_node.go @@ -95,14 +95,14 @@ func (m *MergeNode) setParenthese(hasParen bool) { } // pushFilter used to push the filters. -func (m *MergeNode) pushFilter(filters []filterTuple) error { +func (m *MergeNode) pushFilter(filters []exprInfo) error { var err error for _, filter := range filters { m.addWhere(filter.expr) if len(filter.referTables) == 1 { tbInfo := m.referTables[filter.referTables[0]] if tbInfo.shardKey != "" && len(filter.vals) > 0 { - if nameMatch(filter.col, filter.referTables[0], tbInfo.shardKey) { + if nameMatch(filter.cols[0], filter.referTables[0], tbInfo.shardKey) { for _, val := range filter.vals { if err = getIndex(m.router, tbInfo, val); err != nil { return err @@ -129,7 +129,7 @@ func (m *MergeNode) addHaving(expr sqlparser.Expr) { } // setWhereFilter used to push the where filters. -func (m *MergeNode) setWhereFilter(filter filterTuple) { +func (m *MergeNode) setWhereFilter(filter exprInfo) { m.addWhere(filter.expr) } @@ -141,7 +141,7 @@ func (m *MergeNode) setNoTableFilter(exprs []sqlparser.Expr) { } // pushEqualCmpr used to push the 'join' type filters. -func (m *MergeNode) pushEqualCmpr(joins []joinTuple) SelectNode { +func (m *MergeNode) pushEqualCmpr(joins []exprInfo) SelectNode { for _, joinFilter := range joins { m.addWhere(joinFilter.expr) } @@ -231,7 +231,7 @@ func (m *MergeNode) pushSelectExpr(field selectTuple) (int, error) { } // pushHaving used to push having exprs. -func (m *MergeNode) pushHaving(havings []filterTuple) error { +func (m *MergeNode) pushHaving(havings []exprInfo) error { for _, filter := range havings { m.addHaving(filter.expr) } diff --git a/src/planner/plan_node.go b/src/planner/plan_node.go index 2860d9e1..8e71b908 100644 --- a/src/planner/plan_node.go +++ b/src/planner/plan_node.go @@ -28,16 +28,16 @@ type PlanNode interface { // SelectNode interface. type SelectNode interface { PlanNode - pushFilter(filters []filterTuple) error + pushFilter(filters []exprInfo) error setParent(p SelectNode) - setWhereFilter(filter filterTuple) + setWhereFilter(filter exprInfo) setNoTableFilter(exprs []sqlparser.Expr) setParenthese(hasParen bool) - pushEqualCmpr(joins []joinTuple) SelectNode + pushEqualCmpr(joins []exprInfo) SelectNode calcRoute() (SelectNode, error) pushSelectExprs(fields, groups []selectTuple, sel *sqlparser.Select, aggTyp aggrType) error pushSelectExpr(field selectTuple) (int, error) - pushHaving(havings []filterTuple) error + pushHaving(havings []exprInfo) error pushMisc(sel *sqlparser.Select) reOrder(int) Order() int diff --git a/src/planner/select_plan_test.go b/src/planner/select_plan_test.go index c43766e5..71f9949c 100644 --- a/src/planner/select_plan_test.go +++ b/src/planner/select_plan_test.go @@ -645,7 +645,7 @@ func TestSelectUnsupportedPlan(t *testing.T) { "unsupported: orderby[b].should.in.select.list", "unsupported: limit.offset.or.counts.must.be.IntVal", "unsupported: expr[count(*)].in.having.clause", - "unsupported: unknown.table.'B'.in.clause", + "unsupported: unknown.column.'B.a'.in.clause", "unsupported: invalid.use.of.group.function[count]", "unsupported: 'round(avg(id))'.contain.aggregate.in.select.exprs", "unsupported: group_concat.in.select.exprs",