示例#1
0
func (s *testHavingRsetSuite) TestHavingRsetCheckAndUpdateSelectList(c *C) {
	resultFields := s.r.Src.GetFields()

	selectList := s.r.SelectList

	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{&expression.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 := expression.NewBinaryOperation(opcode.Plus, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.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 := expression.NewCall("count", []expression.Expression{expression.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 = expression.NewCall("count", []expression.Expression{&expression.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 = expression.NewBinaryOperation(opcode.GT, &expression.Ident{CIStr: model.NewCIStr("xxx")}, expression.Value{Val: 1})

	s.r.Expr = expr

	err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields)
	c.Assert(err, NotNil)
}
示例#2
0
func (s *testWhereRsetSuite) SetUpSuite(c *C) {
	names := []string{"id", "name"}
	tblPlan := newTestTablePlan(testData, names)

	expr := expression.NewBinaryOperation(opcode.Plus, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.Value{Val: 1})

	s.r = &WhereRset{Src: tblPlan, Expr: expr}
}
示例#3
0
func (s *testVisitorSuite) TestBase(c *C) {
	val := expression.Value{Val: 1}
	visitor := expression.NewIdentEvalVisitor()
	var exp expression.Expression
	exp = &expression.Between{Expr: val, Left: val, Right: val}
	exp.Accept(visitor)
	exp = expression.NewBinaryOperation(opcode.And, val, val)
	exp.Accept(visitor)
	exp, _ = expression.NewCall("avg", []expression.Expression{val}, true)
	exp.Accept(visitor)
	rows := [][]interface{}{{1}}
	sq := newMockSubQuery(rows, []string{"a"})
	exp = expression.NewCompareSubQuery(opcode.EQ, val, sq, true)
	exp.Accept(visitor)
	exp = &expression.Default{Name: "a"}
	exp.Accept(visitor)
	exp = expression.NewExistsSubQuery(sq)
	exp.Accept(visitor)

	when := &expression.WhenClause{Expr: val, Result: val}
	exp = &expression.FunctionCase{
		WhenClauses: []*expression.WhenClause{when},
		Value:       val,
		ElseClause:  val,
	}
	exp.Accept(visitor)
	exp = &expression.FunctionCast{Expr: val, Tp: types.NewFieldType(mysql.TypeLong), FunctionType: expression.ConvertFunction}
	exp.Accept(visitor)
	exp = &expression.FunctionConvert{Expr: val, Charset: "utf8"}
	exp.Accept(visitor)
	exp = &expression.FunctionSubstring{StrExpr: expression.Value{Val: "string"}, Pos: expression.Value{Val: 0}, Len: val}
	exp.Accept(visitor)
	exp = &expression.IsNull{Expr: val}
	exp.Accept(visitor)
	exp = &expression.IsTruth{Expr: val}
	exp.Accept(visitor)
	exp = &expression.ParamMarker{Expr: val}
	exp.Accept(visitor)
	exp = &expression.PatternIn{Expr: val, List: []expression.Expression{val}}
	exp.Accept(visitor)
	exp = &expression.PatternLike{Expr: val, Pattern: val}
	exp.Accept(visitor)
	exp = &expression.PatternRegexp{Expr: val, Pattern: val}
	exp.Accept(visitor)
	exp = &expression.PExpr{Expr: val}
	exp.Accept(visitor)
	exp = &expression.Position{Name: "a"}
	exp.Accept(visitor)
	exp = &expression.Row{Values: []expression.Expression{val}}
	exp.Accept(visitor)
	exp = &expression.UnaryOperation{V: val}
	exp.Accept(visitor)
	exp = &expression.Values{CIStr: model.NewCIStr("a")}
	exp.Accept(visitor)
	exp = &expression.Variable{Name: "a"}
	exp.Accept(visitor)
}
示例#4
0
func (s *testVisitorSuite) TestIdentEval(c *C) {
	exp := expression.NewBinaryOperation(opcode.Plus, &expression.Ident{CIStr: model.NewCIStr("a")}, expression.Value{Val: 1})
	iev := expression.NewIdentEvalVisitor()
	iev.Set("a", 3)
	exp.Accept(iev)
	v, err := exp.Eval(nil, nil)
	c.Assert(err, IsNil)
	c.Assert(v, Equals, int64(4))
}
示例#5
0
func (s *testGroupByRsetSuite) TestGroupByHasAmbiguousField(c *C) {
	fld := &field.Field{Expr: expression.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: &expression.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 := expression.NewBinaryOperation(opcode.Plus, expression.Value{Val: "c1"},
		expression.Value{Val: "c2"})
	expry := expression.NewBinaryOperation(opcode.Plus, expression.Value{Val: "c1"},
		expression.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: &expression.Ident{CIStr: model.NewCIStr("c1")}, Name: "c2"}
	fldy = &field.Field{Expr: &expression.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)
}
示例#6
0
func (s *testHavingRsetSuite) SetUpSuite(c *C) {
	names := []string{"id", "name"}
	tblPlan := newTestTablePlan(testData, names)

	// expr `id > 1`
	expr := expression.NewBinaryOperation(opcode.GT, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.Value{Val: 1})

	resultFields := tblPlan.GetFields()
	fields := make([]*field.Field, len(resultFields))
	for i, resultField := range resultFields {
		name := resultField.Name
		fields[i] = &field.Field{Expr: &expression.Ident{CIStr: model.NewCIStr(name)}}
	}

	selectList := &plans.SelectList{
		HiddenFieldOffset: len(resultFields),
		ResultFields:      resultFields,
		Fields:            fields,
	}
	s.r = &HavingRset{Src: tblPlan, Expr: expr, SelectList: selectList}
}
示例#7
0
func (c *expressionConverter) binaryOperation(v *ast.BinaryOperationExpr) {
	oldeLeft := c.exprMap[v.L]
	oldRight := c.exprMap[v.R]
	oldBinop := expression.NewBinaryOperation(v.Op, oldeLeft, oldRight)
	c.exprMap[v] = oldBinop
}
示例#8
0
func composeUserTableFilter(name string, host string) expression.Expression {
	nameMatch := expression.NewBinaryOperation(opcode.EQ, &expression.Ident{CIStr: model.NewCIStr("User")}, &expression.Value{Val: name})
	hostMatch := expression.NewBinaryOperation(opcode.EQ, &expression.Ident{CIStr: model.NewCIStr("Host")}, &expression.Value{Val: host})
	return expression.NewBinaryOperation(opcode.AndAnd, nameMatch, hostMatch)
}
示例#9
0
文件: where.go 项目: netroby/tidb
func (r *WhereRset) planBinOp(ctx context.Context, x *expression.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.(*expression.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 := expression.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
}
示例#10
0
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] = expression.Value{Val: "abc"}

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t group by 1`
	s.r.By[0] = expression.Value{Val: int64(1)}

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	s.r.By[0] = expression.Value{Val: uint64(1)}

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t group by 0`
	s.r.By[0] = expression.Value{Val: int64(0)}

	_, err = s.r.Plan(nil)
	c.Assert(err, NotNil)

	fldExpr, err := expression.NewCall("count", []expression.Expression{expression.Value{Val: 1}}, false)
	c.Assert(err, IsNil)

	// `select count(1) as a, name from t group by 1`
	fld := &field.Field{Expr: fldExpr, AsName: "a"}
	s.r.SelectList.Fields[0] = fld

	s.r.By[0] = expression.Value{Val: 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] = &expression.Ident{CIStr: model.NewCIStr("name")}

	fldx := &field.Field{Expr: &expression.Ident{CIStr: model.NewCIStr("id")}, AsName: "name"}
	fldy := &field.Field{Expr: &expression.Ident{CIStr: model.NewCIStr("name")}, AsName: "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 := expression.NewBinaryOperation(opcode.Plus, &expression.Ident{CIStr: model.NewCIStr("a")}, expression.Value{Val: 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)
}
示例#11
0
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: &expression.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{&expression.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 := expression.NewBinaryOperation(opcode.Plus, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.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 := expression.NewCall("count", []expression.Expression{expression.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 = expression.NewCall("count", []expression.Expression{&expression.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 = expression.NewBinaryOperation(opcode.GT, &expression.Ident{CIStr: model.NewCIStr("xxx")}, expression.Value{Val: 1})

	s.r.Expr = expr

	err = s.r.CheckAndUpdateSelectList(selectList, groupBy, resultFields)
	c.Assert(err, NotNil)
}
示例#12
0
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 = expression.Value{Val: int64(1)}

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t where 0`
	s.r.Expr = expression.Value{Val: int64(0)}

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t where null`
	s.r.Expr = expression.Value{}

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t where id < 10`
	expr := expression.NewBinaryOperation(opcode.LT, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.Value{Val: 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 = expression.NewBinaryOperation(opcode.AndAnd, expression.Value{}, expression.Value{Val: 1})

	s.r.Expr = expr

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t where id && 1`
	expr = expression.NewBinaryOperation(opcode.AndAnd, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.Value{Val: 1})

	s.r.Expr = expr

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)

	// `select id, name from t where id && (id < 10)`
	exprx := expression.NewBinaryOperation(opcode.LT, &expression.Ident{CIStr: model.NewCIStr("id")}, expression.Value{Val: 10})
	expr = expression.NewBinaryOperation(opcode.AndAnd, &expression.Ident{CIStr: 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 = &expression.Ident{CIStr: 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 = expression.Value{Val: 1}
	expr = &expression.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 = &expression.Ident{CIStr: model.NewCIStr("id")}
	expr = &expression.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 = &expression.Ident{CIStr: model.NewCIStr("id")}
	expr = expression.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 = &expression.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 := expression.Value{Val: "%s"}
	expr = &expression.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 = &expression.IsTruth{Expr: exprx}
	s.r.Expr = expr

	_, err = s.r.Plan(nil)
	c.Assert(err, IsNil)
}