tidb overflow 源码

2022-09-19 浏览 (601)

tidb overflow 代码

文件路径:/types/overflow.go

/ Copyright 2015 PingCAP, Inc.
/
/ Licensed under the Apache License, Version 2.0 (the "License");
/ you may not use this file except in compliance with the License.
/ You may obtain a copy of the License at
/
/     http://www.apache.org/licenses/LICENSE-2.0
/
/ Unless required by applicable law or agreed to in writing, software
/ distributed under the License is distributed on an "AS IS" BASIS,
/ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
/ See the License for the specific language governing permissions and
/ limitations under the License.

package types

import (
	"fmt"
	"math"
	"time"

	"github.com/pingcap/errors"
)

/ AddUint64 adds uint64 a and b if no overflow, else returns error.
func AddUint64(a uint64, b uint64) (uint64, error) {
	if math.MaxUint64-a < b {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
	}
	return a + b, nil
}

/ AddInt64 adds int64 a and b if no overflow, otherwise returns error.
func AddInt64(a int64, b int64) (int64, error) {
	if (a > 0 && b > 0 && math.MaxInt64-a < b) ||
		(a < 0 && b < 0 && math.MinInt64-a > b) {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", a, b))
	}

	return a + b, nil
}

/ AddDuration adds time.Duration a and b if no overflow, otherwise returns error.
func AddDuration(a time.Duration, b time.Duration) (time.Duration, error) {
	if (a > 0 && b > 0 && math.MaxInt64-a < b) ||
		(a < 0 && b < 0 && math.MinInt64-a > b) {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", int64(a), int64(b)))
	}

	return a + b, nil
}

/ SubDuration subtracts time.Duration a with b and returns time.Duration if no overflow error.
func SubDuration(a time.Duration, b time.Duration) (time.Duration, error) {
	if (a > 0 && b < 0 && math.MaxInt64-a < -b) ||
		(a < 0 && b > 0 && math.MinInt64-a > -b) ||
		(a == 0 && b == math.MinInt64) {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", a, b))
	}
	return a - b, nil
}

/ AddInteger adds uint64 a and int64 b and returns uint64 if no overflow error.
func AddInteger(a uint64, b int64) (uint64, error) {
	if b >= 0 {
		return AddUint64(a, uint64(b))
	}

	if uint64(-b) > a {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
	}
	return a - uint64(-b), nil
}

/ SubUint64 subtracts uint64 a with b and returns uint64 if no overflow error.
func SubUint64(a uint64, b uint64) (uint64, error) {
	if a < b {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
	}
	return a - b, nil
}

/ SubInt64 subtracts int64 a with b and returns int64 if no overflow error.
func SubInt64(a int64, b int64) (int64, error) {
	if (a > 0 && b < 0 && math.MaxInt64-a < -b) ||
		(a < 0 && b > 0 && math.MinInt64-a > -b) ||
		(a == 0 && b == math.MinInt64) {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", a, b))
	}
	return a - b, nil
}

/ SubUintWithInt subtracts uint64 a with int64 b and returns uint64 if no overflow error.
func SubUintWithInt(a uint64, b int64) (uint64, error) {
	if b < 0 {
		return AddUint64(a, uint64(-b))
	}
	return SubUint64(a, uint64(b))
}

/ SubIntWithUint subtracts int64 a with uint64 b and returns uint64 if no overflow error.
func SubIntWithUint(a int64, b uint64) (uint64, error) {
	if a < 0 || uint64(a) < b {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
	}
	return uint64(a) - b, nil
}

/ MulUint64 multiplies uint64 a and b and returns uint64 if no overflow error.
func MulUint64(a uint64, b uint64) (uint64, error) {
	if b > 0 && a > math.MaxUint64/b {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
	}
	return a * b, nil
}

/ MulInt64 multiplies int64 a and b and returns int64 if no overflow error.
func MulInt64(a int64, b int64) (int64, error) {
	if a == 0 || b == 0 {
		return 0, nil
	}

	var (
		res      uint64
		err      error
		negative = false
	)

	if a > 0 && b > 0 {
		res, err = MulUint64(uint64(a), uint64(b))
	} else if a < 0 && b < 0 {
		res, err = MulUint64(uint64(-a), uint64(-b))
	} else if a < 0 && b > 0 {
		negative = true
		res, err = MulUint64(uint64(-a), uint64(b))
	} else {
		negative = true
		res, err = MulUint64(uint64(a), uint64(-b))
	}

	if err != nil {
		return 0, errors.Trace(err)
	}

	if negative {
		/ negative result
		if res > math.MaxInt64+1 {
			return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", a, b))
		}

		return -int64(res), nil
	}

	/ positive result
	if res > math.MaxInt64 {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", a, b))
	}

	return int64(res), nil
}

/ MulInteger multiplies uint64 a and int64 b, and returns uint64 if no overflow error.
func MulInteger(a uint64, b int64) (uint64, error) {
	if a == 0 || b == 0 {
		return 0, nil
	}

	if b < 0 {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
	}

	return MulUint64(a, uint64(b))
}

/ DivInt64 divides int64 a with b, returns int64 if no overflow error.
/ It just checks overflow, if b is zero, a "divide by zero" panic throws.
func DivInt64(a int64, b int64) (int64, error) {
	if a == math.MinInt64 && b == -1 {
		return 0, ErrOverflow.GenWithStackByArgs("BIGINT", fmt.Sprintf("(%d, %d)", a, b))
	}

	return a / b, nil
}

/ DivUintWithInt divides uint64 a with int64 b, returns uint64 if no overflow error.
/ It just checks overflow, if b is zero, a "divide by zero" panic throws.
func DivUintWithInt(a uint64, b int64) (uint64, error) {
	if b < 0 {
		if a != 0 && uint64(-b) <= a {
			return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
		}

		return 0, nil
	}

	return a / uint64(b), nil
}

/ DivIntWithUint divides int64 a with uint64 b, returns uint64 if no overflow error.
/ It just checks overflow, if b is zero, a "divide by zero" panic throws.
func DivIntWithUint(a int64, b uint64) (uint64, error) {
	if a < 0 {
		if uint64(-a) >= b {
			return 0, ErrOverflow.GenWithStackByArgs("BIGINT UNSIGNED", fmt.Sprintf("(%d, %d)", a, b))
		}

		return 0, nil
	}

	return uint64(a) / b, nil
}

相关信息

tidb 源码目录

相关文章

tidb binary_literal 源码

tidb compare 源码

tidb convert 源码

tidb core_time 源码

tidb datum 源码

tidb datum_eval 源码

tidb enum 源码

tidb errors 源码

tidb etc 源码

tidb eval_type 源码

^