func (s *testWhereRsetSuite) SetUpSuite(c *C) { names := []string{"id", "name"} tblPlan := newTestTablePlan(testData, names) expr := expressions.NewBinaryOperation(opcode.Plus, &expressions.Ident{model.NewCIStr("id")}, expressions.Value{1}) s.r = &WhereRset{Src: tblPlan, Expr: expr} }
func (s *testHavingRsetSuite) SetUpSuite(c *C) { names := []string{"id", "name"} tblPlan := newTestTablePlan(testData, names) // expr `id > 1` expr := expressions.NewBinaryOperation(opcode.GT, &expressions.Ident{CIStr: model.NewCIStr("id")}, expressions.Value{Val: 1}) s.r = &HavingRset{Src: tblPlan, Expr: expr} }
func (s *testGroupByRsetSuite) TestGroupByHasAmbiguousField(c *C) { fld := &field.Field{Expr: expressions.Value{Val: 1}} // check `1` fields := []*field.Field{fld} indices := []int{0} ret := s.r.HasAmbiguousField(indices, fields) c.Assert(ret, IsFalse) // check `c1 as c2, c1 as c2` fld = &field.Field{Expr: &expressions.Ident{CIStr: model.NewCIStr("c1")}, Name: "c2"} fields = []*field.Field{fld, fld} indices = []int{0, 1} ret = s.r.HasAmbiguousField(indices, fields) c.Assert(ret, IsFalse) // check `c1+c2 as c2, c1+c3 as c2` exprx := expressions.NewBinaryOperation(opcode.Plus, expressions.Value{Val: "c1"}, expressions.Value{Val: "c2"}) expry := expressions.NewBinaryOperation(opcode.Plus, expressions.Value{Val: "c1"}, expressions.Value{Val: "c3"}) fldx := &field.Field{Expr: exprx, Name: "c2"} fldy := &field.Field{Expr: expry, Name: "c2"} fields = []*field.Field{fldx, fldy} indices = []int{0, 1} ret = s.r.HasAmbiguousField(indices, fields) c.Assert(ret, IsFalse) // check `c1 as c2, c3 as c2` fldx = &field.Field{Expr: &expressions.Ident{CIStr: model.NewCIStr("c1")}, Name: "c2"} fldy = &field.Field{Expr: &expressions.Ident{CIStr: model.NewCIStr("c3")}, Name: "c2"} fields = []*field.Field{fldx, fldy} indices = []int{0, 1} ret = s.r.HasAmbiguousField(indices, fields) c.Assert(ret, IsTrue) }
func (s *testGroupByRsetSuite) TestGroupByRsetPlan(c *C) { // `select id, name from t group by name` p, err := s.r.Plan(nil) c.Assert(err, IsNil) _, ok := p.(*plans.GroupByDefaultPlan) c.Assert(ok, IsTrue) // `select id, name from t group by abc` s.r.By[0] = expressions.Value{"abc"} _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t group by 1` s.r.By[0] = expressions.Value{int64(1)} _, err = s.r.Plan(nil) c.Assert(err, IsNil) s.r.By[0] = expressions.Value{uint64(1)} _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t group by 0` s.r.By[0] = expressions.Value{int64(0)} _, err = s.r.Plan(nil) c.Assert(err, NotNil) fldExpr, err := expressions.NewCall("count", []expression.Expression{expressions.Value{1}}, false) c.Assert(err, IsNil) // `select count(1) as a, name from t group by 1` fld := &field.Field{Expr: fldExpr, Name: "a"} s.r.SelectList.Fields[0] = fld s.r.By[0] = expressions.Value{int64(1)} _, err = s.r.Plan(nil) c.Assert(err, NotNil) // check ambiguous field, like `select id as name, name from t group by name` s.r.By[0] = &expressions.Ident{model.NewCIStr("name")} fldx := &field.Field{Expr: &expressions.Ident{CIStr: model.NewCIStr("id")}, Name: "name"} fldy := &field.Field{Expr: &expressions.Ident{CIStr: model.NewCIStr("name")}, Name: "name"} s.r.SelectList.Fields = []*field.Field{fldx, fldy} s.r.SelectList.ResultFields[0].Name = "name" s.r.SelectList.ResultFields[1].Name = "name" p, err = s.r.Plan(nil) c.Assert(err, NotNil) // check aggregate function reference, like `select count(1) as a, name from t group by a + 1` expr := expressions.NewBinaryOperation(opcode.Plus, &expressions.Ident{model.NewCIStr("a")}, expressions.Value{1}) s.r.By[0] = expr s.r.SelectList.Fields[0] = fld s.r.SelectList.ResultFields[0].Col.Name = model.NewCIStr("count(id)") s.r.SelectList.ResultFields[0].Name = "a" _, err = s.r.Plan(nil) c.Assert(err, NotNil) // check contain aggregate function, like `select count(1) as a, name from t group by count(1)` s.r.By[0] = fldExpr _, err = s.r.Plan(nil) c.Assert(err, NotNil) }
func composeUserTableFilter(name string, host string) expression.Expression { nameMatch := expressions.NewBinaryOperation(opcode.EQ, &expressions.Ident{CIStr: model.NewCIStr("User")}, &expressions.Value{Val: name}) hostMatch := expressions.NewBinaryOperation(opcode.EQ, &expressions.Ident{CIStr: model.NewCIStr("Host")}, &expressions.Value{Val: host}) return expressions.NewBinaryOperation(opcode.AndAnd, nameMatch, hostMatch) }
func (r *WhereRset) planBinOp(ctx context.Context, x *expressions.BinaryOperation) (plan.Plan, error) { var err error var p2 plan.Plan var filtered bool p := r.Src switch x.Op { case opcode.EQ, opcode.GE, opcode.GT, opcode.LE, opcode.LT, opcode.NE: if p2, filtered, err = p.Filter(ctx, x); err != nil { return nil, err } if filtered { return p2, nil } case opcode.AndAnd: var in []expression.Expression var f func(expression.Expression) f = func(e expression.Expression) { b, ok := e.(*expressions.BinaryOperation) if !ok || b.Op != opcode.AndAnd { in = append(in, e) return } f(b.L) f(b.R) } f(x) out := []expression.Expression{} p := r.Src isNewPlan := false for _, e := range in { p2, filtered, err = p.Filter(ctx, e) if err != nil { return nil, err } if !filtered { out = append(out, e) continue } p = p2 isNewPlan = true } if !isNewPlan { break } if len(out) == 0 { return p, nil } for len(out) > 1 { n := len(out) e := expressions.NewBinaryOperation(opcode.AndAnd, out[n-2], out[n-1]) out = out[:n-1] out[n-2] = e } return &plans.FilterDefaultPlan{Plan: p, Expr: out[0]}, nil default: // TODO: better plan for `OR`. log.Warn("TODO: better plan for", x.Op) } return &plans.FilterDefaultPlan{Plan: p, Expr: x}, nil }
func (s *testHavingRsetSuite) TestHavingRsetCheckAndUpdateSelectList(c *C) { resultFields := s.r.Src.GetFields() fields := make([]*field.Field, len(resultFields)) for i, resultField := range resultFields { name := resultField.Name fields[i] = &field.Field{Expr: &expressions.Ident{CIStr: model.NewCIStr(name)}, Name: name} } selectList := &plans.SelectList{ HiddenFieldOffset: len(resultFields), ResultFields: resultFields, Fields: fields, } groupBy := []expression.Expression{} // `select id, name from t having id > 1` err := s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, IsNil) // `select name from t group by id having id > 1` selectList.ResultFields = selectList.ResultFields[1:] selectList.Fields = selectList.Fields[1:] groupBy = []expression.Expression{&expressions.Ident{CIStr: model.NewCIStr("id")}} err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, IsNil) // `select name from t group by id + 1 having id > 1` expr := expressions.NewBinaryOperation(opcode.Plus, &expressions.Ident{CIStr: model.NewCIStr("id")}, expressions.Value{Val: 1}) groupBy = []expression.Expression{expr} err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, IsNil) // `select name from t group by id + 1 having count(1) > 1` aggExpr, err := expressions.NewCall("count", []expression.Expression{expressions.Value{Val: 1}}, false) c.Assert(err, IsNil) s.r.Expr = aggExpr err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, IsNil) // `select name from t group by id + 1 having count(xxx) > 1` aggExpr, err = expressions.NewCall("count", []expression.Expression{&expressions.Ident{CIStr: model.NewCIStr("xxx")}}, false) c.Assert(err, IsNil) s.r.Expr = aggExpr err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, NotNil) // `select name from t group by id having xxx > 1` expr = expressions.NewBinaryOperation(opcode.GT, &expressions.Ident{CIStr: model.NewCIStr("xxx")}, expressions.Value{Val: 1}) s.r.Expr = expr err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, NotNil) s.r.Expr = &expressions.Row{Values: []expression.Expression{expressions.Value{Val: 1}, expressions.Value{Val: 1}}} err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields) c.Assert(err, NotNil) }
func (s *testWhereRsetSuite) TestShowRsetPlan(c *C) { // `select id, name from t where id + 1` p, err := s.r.Plan(nil) c.Assert(err, IsNil) _, ok := p.(*plans.FilterDefaultPlan) c.Assert(ok, IsTrue) // `select id, name from t where 1` s.r.Expr = expressions.Value{int64(1)} _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where 0` s.r.Expr = expressions.Value{int64(0)} _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where null` s.r.Expr = expressions.Value{} _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id < 10` expr := expressions.NewBinaryOperation(opcode.LT, &expressions.Ident{model.NewCIStr("id")}, expressions.Value{10}) s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) src := s.r.Src.(*testTablePlan) src.SetFilter(true) _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where null && 1` src.SetFilter(false) expr = expressions.NewBinaryOperation(opcode.AndAnd, expressions.Value{}, expressions.Value{1}) s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id && 1` expr = expressions.NewBinaryOperation(opcode.AndAnd, &expressions.Ident{model.NewCIStr("id")}, expressions.Value{1}) s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id && (id < 10)` exprx := expressions.NewBinaryOperation(opcode.LT, &expressions.Ident{model.NewCIStr("id")}, expressions.Value{10}) expr = expressions.NewBinaryOperation(opcode.AndAnd, &expressions.Ident{model.NewCIStr("id")}, exprx) s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) src.SetFilter(true) _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where abc` src.SetFilter(false) expr = &expressions.Ident{model.NewCIStr("abc")} s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) src.SetFilter(true) _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where 1 is null` src.SetFilter(false) exprx = expressions.Value{1} expr = &expressions.IsNull{Expr: exprx} s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) src.SetFilter(true) _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id is null` src.SetFilter(false) exprx = &expressions.Ident{model.NewCIStr("id")} expr = &expressions.IsNull{Expr: exprx} s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) src.SetFilter(true) _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where +id` src.SetFilter(false) exprx = &expressions.Ident{model.NewCIStr("id")} expr = expressions.NewUnaryOperation(opcode.Plus, exprx) s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) src.SetFilter(true) _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id in (id)` expr = &expressions.PatternIn{Expr: exprx, List: []expression.Expression{exprx}} s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id like '%s'` expry := expressions.Value{"%s"} expr = &expressions.PatternLike{Expr: exprx, Pattern: expry} s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) // `select id, name from t where id is true` expr = &expressions.IsTruth{Expr: exprx} s.r.Expr = expr _, err = s.r.Plan(nil) c.Assert(err, IsNil) }