Skip to content

Commit

Permalink
planner: refactor the filterTuple radondb#480
Browse files Browse the repository at this point in the history
[summary]
merge the filterTuple and joinTuple.
[test case]
src/planner/from_test.go
src/planner/select_plan_test.go
[patch codecov]
96.9%
  • Loading branch information
zhyass authored and BohuTANG committed Oct 31, 2019
1 parent d8578f8 commit 61723d6
Show file tree
Hide file tree
Showing 7 changed files with 78 additions and 89 deletions.
57 changes: 23 additions & 34 deletions src/planner/expr.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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())
}
}

Expand All @@ -546,24 +535,23 @@ 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)
if err != nil {
return nil, nil, err
}

if count != 1 {
col = nil
}
condition, ok := filter.(*sqlparser.ComparisonExpr)
if ok {
lc, lok := condition.Left.(*sqlparser.ColName)
rc, rok := condition.Right.(*sqlparser.ColName)
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
}
Expand All @@ -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:
Expand All @@ -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")
Expand All @@ -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
}
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}

Expand All @@ -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{}
}
Expand Down
8 changes: 4 additions & 4 deletions src/planner/from.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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)
}
}
Expand All @@ -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)
Expand Down
4 changes: 2 additions & 2 deletions src/planner/from_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)",
Expand Down
Loading

0 comments on commit 61723d6

Please sign in to comment.