コード例 #1
0
ファイル: builtin_other.go プロジェクト: yuyongwei/tidb
func arithmeticFuncFactory(op opcode.Op) BuiltinFunc {
	return func(args []types.Datum, _ context.Context) (d types.Datum, err error) {
		a, err := types.CoerceArithmetic(args[0])
		if err != nil {
			return d, errors.Trace(err)
		}

		b, err := types.CoerceArithmetic(args[1])
		if err != nil {
			return d, errors.Trace(err)
		}

		a, b = types.CoerceDatum(a, b)
		if a.IsNull() || b.IsNull() {
			return
		}

		switch op {
		case opcode.Plus:
			return types.ComputePlus(a, b)
		case opcode.Minus:
			return types.ComputeMinus(a, b)
		case opcode.Mul:
			return types.ComputeMul(a, b)
		case opcode.Div:
			return types.ComputeDiv(a, b)
		case opcode.Mod:
			return types.ComputeMod(a, b)
		case opcode.IntDiv:
			return types.ComputeIntDiv(a, b)
		default:
			return d, ErrInvalidOperation.Gen("invalid op %v in arithmetic operation", op)
		}
	}
}
コード例 #2
0
ファイル: eval_bit_ops.go プロジェクト: jmptrader/tidb
// ComputeBit computes the bitwise operation on two datums.
func ComputeBit(op tipb.ExprType, left, right types.Datum) (types.Datum, error) {
	var result types.Datum
	a, err := types.CoerceArithmetic(left)
	if err != nil {
		return result, errors.Trace(err)
	}

	b, err := types.CoerceArithmetic(right)
	if err != nil {
		return result, errors.Trace(err)
	}
	a, b, err = types.CoerceDatum(a, b)
	if err != nil {
		return result, errors.Trace(err)
	}
	if a.IsNull() || b.IsNull() {
		return result, nil
	}

	switch op {
	case tipb.ExprType_BitAnd:
		return types.ComputeBitAnd(a, b)
	case tipb.ExprType_BitOr:
		return types.ComputeBitOr(a, b)
	case tipb.ExprType_BitXor:
		return types.ComputeBitXor(a, b)
	case tipb.ExprType_LeftShift:
		return types.ComputeLeftShift(a, b)
	case tipb.ExprType_RighShift:
		return types.ComputeRightShift(a, b)
	default:
		return result, errors.Errorf("Unknown binop type: %v", op)
	}
}
コード例 #3
0
ファイル: builtin_other.go プロジェクト: yuyongwei/tidb
// See http://dev.mysql.com/doc/refman/5.7/en/any-in-some-subqueries.html
func builtinIn(args []types.Datum, _ context.Context) (d types.Datum, err error) {
	if args[0].IsNull() {
		return
	}

	var hasNull bool
	for _, v := range args[1:] {
		if v.IsNull() {
			hasNull = true
			continue
		}

		a, b := types.CoerceDatum(args[0], v)
		ret, err := a.CompareDatum(b)
		if err != nil {
			return d, errors.Trace(err)
		}
		if ret == 0 {
			d.SetInt64(1)
			return d, nil
		}
	}

	if hasNull {
		// If it's no matched but we get null in In, returns null.
		// e.g 1 in (null, 2, 3) returns null.
		return
	}
	d.SetInt64(0)
	return
}
コード例 #4
0
ファイル: builtin_other.go プロジェクト: yuyongwei/tidb
func bitOpFactory(op opcode.Op) BuiltinFunc {
	return func(args []types.Datum, _ context.Context) (d types.Datum, err error) {
		a, b := types.CoerceDatum(args[0], args[1])
		if a.IsNull() || b.IsNull() {
			return
		}

		x, err := a.ToInt64()
		if err != nil {
			return d, errors.Trace(err)
		}

		y, err := b.ToInt64()
		if err != nil {
			return d, errors.Trace(err)
		}

		// use a int64 for bit operator, return uint64
		switch op {
		case opcode.And:
			d.SetUint64(uint64(x & y))
		case opcode.Or:
			d.SetUint64(uint64(x | y))
		case opcode.Xor:
			d.SetUint64(uint64(x ^ y))
		case opcode.RightShift:
			d.SetUint64(uint64(x) >> uint64(y))
		case opcode.LeftShift:
			d.SetUint64(uint64(x) << uint64(y))
		default:
			return d, ErrInvalidOperation.Gen("invalid op %v in bit operation", op)
		}
		return
	}
}
コード例 #5
0
ファイル: eval.go プロジェクト: XuHuaiyu/tidb
// ComputeArithmetic computes the arithmetic operation on two datums.
func ComputeArithmetic(op tipb.ExprType, left types.Datum, right types.Datum) (types.Datum, error) {
	var result types.Datum
	a, err := types.CoerceArithmetic(left)
	if err != nil {
		return result, errors.Trace(err)
	}

	b, err := types.CoerceArithmetic(right)
	if err != nil {
		return result, errors.Trace(err)
	}
	a, b = types.CoerceDatum(a, b)
	if a.IsNull() || b.IsNull() {
		return result, nil
	}

	switch op {
	case tipb.ExprType_Plus:
		return types.ComputePlus(a, b)
	case tipb.ExprType_Div:
		return types.ComputeDiv(a, b)
	default:
		return result, errors.Errorf("Unknown binop type: %v", op)
	}
}
コード例 #6
0
ファイル: eval.go プロジェクト: anywhy/tidb
func (e *Evaluator) evalArithmetic(expr *tipb.Expr) (types.Datum, error) {
	var result types.Datum
	left, right, err := e.evalTwoChildren(expr)
	if err != nil {
		return result, errors.Trace(err)
	}
	a, err := types.CoerceArithmetic(left)
	if err != nil {
		return result, errors.Trace(err)
	}

	b, err := types.CoerceArithmetic(right)
	if err != nil {
		return result, errors.Trace(err)
	}
	a, b = types.CoerceDatum(a, b)
	if a.IsNull() || b.IsNull() {
		return result, nil
	}

	switch expr.GetTp() {
	case tipb.ExprType_Plus:
		return types.ComputePlus(a, b)
	case tipb.ExprType_Div:
		return types.ComputeDiv(a, b)
	default:
		return result, errors.Errorf("Unknown binop type: %v", expr.GetTp())
	}
}
コード例 #7
0
ファイル: builtin_other.go プロジェクト: jmptrader/tidb
func compareFuncFactory(op opcode.Op) BuiltinFunc {
	return func(args []types.Datum, _ context.Context) (d types.Datum, err error) {
		var a, b = args[0], args[1]
		if op != opcode.NullEQ {
			a, b, err = types.CoerceDatum(a, b)
			if err != nil {
				return d, errors.Trace(err)
			}
		}
		if a.IsNull() || b.IsNull() {
			// for <=>, if a and b are both nil, return true.
			// if a or b is nil, return false.
			if op == opcode.NullEQ {
				if a.IsNull() && b.IsNull() {
					d.SetInt64(oneI64)
				} else {
					d.SetInt64(zeroI64)
				}
			}
			return
		}

		n, err := a.CompareDatum(b)
		if err != nil {
			return d, errors.Trace(err)
		}
		var result bool
		switch op {
		case opcode.LT:
			result = n < 0
		case opcode.LE:
			result = n <= 0
		case opcode.EQ, opcode.NullEQ:
			result = n == 0
		case opcode.GT:
			result = n > 0
		case opcode.GE:
			result = n >= 0
		case opcode.NE:
			result = n != 0
		default:
			return d, ErrInvalidOperation.Gen("invalid op %v in comparison operation", op)
		}
		if result {
			d.SetInt64(oneI64)
		} else {
			d.SetInt64(zeroI64)
		}
		return
	}
}
コード例 #8
0
ファイル: evaluator_binop.go プロジェクト: pingcap/tidb
func (e *Evaluator) handleComparisonOp(o *ast.BinaryOperationExpr) bool {
	var a, b = *o.L.GetDatum(), *o.R.GetDatum()
	var err error
	if o.Op != opcode.NullEQ {
		a, b, err = types.CoerceDatum(e.sc, *o.L.GetDatum(), *o.R.GetDatum())
		if err != nil {
			e.err = errors.Trace(err)
			return false
		}
	}
	if a.IsNull() || b.IsNull() {
		// for <=>, if a and b are both nil, return true.
		// if a or b is nil, return false.
		if o.Op == opcode.NullEQ {
			if a.IsNull() && b.IsNull() {
				o.SetInt64(oneI64)
			} else {
				o.SetInt64(zeroI64)
			}
		} else {
			o.SetNull()
		}
		return true
	}

	n, err := a.CompareDatum(e.sc, b)

	if err != nil {
		e.err = errors.Trace(err)
		return false
	}

	r, err := getCompResult(o.Op, n)
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}
	if r {
		o.SetInt64(oneI64)
	} else {
		o.SetInt64(zeroI64)
	}
	return true
}
コード例 #9
0
ファイル: evaluator_binop.go プロジェクト: pingcap/tidb
func (e *Evaluator) handleArithmeticOp(o *ast.BinaryOperationExpr) bool {
	a, err := types.CoerceArithmetic(e.sc, *o.L.GetDatum())
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}
	b, err := types.CoerceArithmetic(e.sc, *o.R.GetDatum())
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}

	a, b, err = types.CoerceDatum(e.sc, a, b)
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}
	if a.IsNull() || b.IsNull() {
		o.SetNull()
		return true
	}

	var result types.Datum
	switch o.Op {
	case opcode.Plus:
		result, e.err = types.ComputePlus(a, b)
	case opcode.Minus:
		result, e.err = types.ComputeMinus(a, b)
	case opcode.Mul:
		result, e.err = types.ComputeMul(a, b)
	case opcode.Div:
		result, e.err = types.ComputeDiv(e.sc, a, b)
	case opcode.Mod:
		result, e.err = types.ComputeMod(e.sc, a, b)
	case opcode.IntDiv:
		result, e.err = types.ComputeIntDiv(e.sc, a, b)
	default:
		e.err = ErrInvalidOperation.Gen("invalid op %v in arithmetic operation", o.Op)
		return false
	}
	o.SetDatum(result)
	return e.err == nil
}
コード例 #10
0
ファイル: evaluator_binop.go プロジェクト: pingcap/tidb
func (e *Evaluator) handleBitOp(o *ast.BinaryOperationExpr) bool {
	a, b, err := types.CoerceDatum(e.sc, *o.L.GetDatum(), *o.R.GetDatum())
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}
	if a.IsNull() || b.IsNull() {
		o.SetNull()
		return true
	}

	x, err := a.ToInt64(e.sc)
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}

	y, err := b.ToInt64(e.sc)
	if err != nil {
		e.err = errors.Trace(err)
		return false
	}

	// use a int64 for bit operator, return uint64
	switch o.Op {
	case opcode.And:
		o.SetUint64(uint64(x & y))
	case opcode.Or:
		o.SetUint64(uint64(x | y))
	case opcode.Xor:
		o.SetUint64(uint64(x ^ y))
	case opcode.RightShift:
		o.SetUint64(uint64(x) >> uint64(y))
	case opcode.LeftShift:
		o.SetUint64(uint64(x) << uint64(y))
	default:
		e.err = ErrInvalidOperation.Gen("invalid op %v in bit operation", o.Op)
		return false
	}
	return true
}
コード例 #11
0
ファイル: evaluator.go プロジェクト: yangxuanjia/tidb
func (e *Evaluator) checkInList(not bool, in types.Datum, list []types.Datum) (d types.Datum) {
	hasNull := false
	for _, v := range list {
		if v.IsNull() {
			hasNull = true
			continue
		}

		a, b, err := types.CoerceDatum(in, v)
		if err != nil {
			e.err = errors.Trace(err)
			return d
		}
		r, err := a.CompareDatum(b)
		if err != nil {
			e.err = errors.Trace(err)
			return d
		}
		if r == 0 {
			if !not {
				d.SetInt64(1)
				return d
			}
			d.SetInt64(0)
			return d
		}
	}

	if hasNull {
		// If no matched but we got null in In, return null.
		// e.g 1 in (null, 2, 3) returns null.
		return d
	}
	if not {
		d.SetInt64(1)
		return d
	}
	d.SetInt64(0)
	return d
}
コード例 #12
0
ファイル: eval_arithmetic_ops.go プロジェクト: pingcap/tidb
// ComputeArithmetic computes the arithmetic operation on two datums.
func ComputeArithmetic(sc *variable.StatementContext, op tipb.ExprType, left types.Datum, right types.Datum) (types.Datum, error) {
	var result types.Datum
	a, err := types.CoerceArithmetic(sc, left)
	if err != nil {
		return result, errors.Trace(err)
	}

	b, err := types.CoerceArithmetic(sc, right)
	if err != nil {
		return result, errors.Trace(err)
	}
	a, b, err = types.CoerceDatum(sc, a, b)
	if err != nil {
		return result, errors.Trace(err)
	}
	if a.IsNull() || b.IsNull() {
		return result, nil
	}

	switch op {
	case tipb.ExprType_Plus:
		return types.ComputePlus(a, b)
	case tipb.ExprType_Div:
		return types.ComputeDiv(sc, a, b)
	case tipb.ExprType_Minus:
		return types.ComputeMinus(a, b)
	case tipb.ExprType_Mul:
		return types.ComputeMul(a, b)
	case tipb.ExprType_IntDiv:
		return types.ComputeIntDiv(sc, a, b)
	case tipb.ExprType_Mod:
		return types.ComputeMod(sc, a, b)
	default:
		return result, errors.Errorf("Unknown binop type: %v", op)
	}
}