diff options
author | Ting-Wei Lan <tingwei.lan@cobinhood.com> | 2019-03-27 15:14:11 +0800 |
---|---|---|
committer | lantw44 <lantw44@gmail.com> | 2019-03-29 18:40:42 +0800 |
commit | 370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec (patch) | |
tree | 01a3f220d352a6026407199c1f0aa7b8241aee81 /core/vm/sqlvm/ast/types.go | |
parent | 55f8e6a9c909256d1e363d787e2df96abc7ffa44 (diff) | |
download | dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.tar dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.tar.gz dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.tar.bz2 dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.tar.lz dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.tar.xz dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.tar.zst dexon-370d3ff3e9de2c05f6741dc1b2e7a9d7f439d7ec.zip |
core: vm: sqlvm: ast: don't calculate min and max values on demand
It is unsafe to write a map concurrently. Even if it is unlikely for us
to call it from multiple threads, it is better to avoid providing an
thread-unsafe API when it is possible.
Diffstat (limited to 'core/vm/sqlvm/ast/types.go')
-rw-r--r-- | core/vm/sqlvm/ast/types.go | 101 |
1 files changed, 61 insertions, 40 deletions
diff --git a/core/vm/sqlvm/ast/types.go b/core/vm/sqlvm/ast/types.go index d75d29294..41c35ac78 100644 --- a/core/vm/sqlvm/ast/types.go +++ b/core/vm/sqlvm/ast/types.go @@ -16,14 +16,6 @@ var ( bigIntTen = big.NewInt(10) ) -type decPair struct { - Min, Max decimal.Decimal -} - -var ( - decPairMap = make(map[DataType]decPair) -) - // DataTypeMajor defines type for high byte of DataType. type DataTypeMajor uint8 @@ -152,6 +144,67 @@ func (dt DataType) GetNode() TypeNode { return nil } +type decimalMinMaxPair struct { + Min, Max decimal.Decimal +} + +var decimalMinMaxMap = func() map[DataType]decimalMinMaxPair { + m := make(map[DataType]decimalMinMaxPair) + + // bool + { + dt := ComposeDataType(DataTypeMajorBool, DataTypeMinorDontCare) + m[dt] = decimalMinMaxPair{Min: dec.False, Max: dec.True} + } + + // address + { + dt := ComposeDataType(DataTypeMajorAddress, DataTypeMinorDontCare) + bigMax := new(big.Int) + bigMax.Lsh(bigIntOne, common.AddressLength*8) + bigMax.Sub(bigMax, bigIntOne) + max := decimal.NewFromBigInt(bigMax, 0) + m[dt] = decimalMinMaxPair{Min: decimal.Zero, Max: max} + } + + // uint, bytes{X} + for i := uint(0); i <= 0x1f; i++ { + dtUint := ComposeDataType(DataTypeMajorUint, DataTypeMinor(i)) + dtBytes := ComposeDataType(DataTypeMajorFixedBytes, DataTypeMinor(i)) + bigMax := new(big.Int) + bigMax.Lsh(bigIntOne, (i+1)*8) + bigMax.Sub(bigMax, bigIntOne) + max := decimal.NewFromBigInt(bigMax, 0) + m[dtUint] = decimalMinMaxPair{Min: decimal.Zero, Max: max} + m[dtBytes] = decimalMinMaxPair{Min: decimal.Zero, Max: max} + } + + // int + for i := uint(0); i <= 0x1f; i++ { + dt := ComposeDataType(DataTypeMajorInt, DataTypeMinor(i)) + bigMax := new(big.Int) + bigMax.Lsh(bigIntOne, (i+1)*8-1) + bigMin := new(big.Int) + bigMin.Neg(bigMax) + bigMax.Sub(bigMax, bigIntOne) + min := decimal.NewFromBigInt(bigMin, 0) + max := decimal.NewFromBigInt(bigMax, 0) + m[dt] = decimalMinMaxPair{Min: min, Max: max} + } + + return m +}() + +// GetMinMax returns min, max pair according to given data type. +func (dt DataType) GetMinMax() (decimal.Decimal, decimal.Decimal, bool) { + var ( + pair decimalMinMaxPair + ok bool + ) + pair, ok = decimalMinMaxMap[dt] + return pair.Min, pair.Max, ok +} + func decimalToBig(d decimal.Decimal) (b *big.Int) { if exponent := int64(d.Exponent()); exponent >= 0 { exp := new(big.Int).Exp(bigIntTen, big.NewInt(exponent), nil) @@ -254,38 +307,6 @@ func DecimalDecode(dt DataType, b []byte) (decimal.Decimal, error) { return decimal.Zero, se.ErrorCodeDecimalDecode } -// GetMinMax returns min, max pair according to given data type. -func GetMinMax(dt DataType) (min, max decimal.Decimal, err error) { - cached, ok := decPairMap[dt] - if ok { - min, max = cached.Min, cached.Max - return - } - - major, minor := DecomposeDataType(dt) - switch major { - case DataTypeMajorBool: - min, max = dec.False, dec.True - case DataTypeMajorAddress: - bigUMax := new(big.Int).Lsh(bigIntOne, common.AddressLength*8) - max = decimal.NewFromBigInt(bigUMax, 0).Sub(dec.One) - case DataTypeMajorInt: - bigMax := new(big.Int).Lsh(bigIntOne, (uint(minor)+1)*8-1) - decMax := decimal.NewFromBigInt(bigMax, 0) - min, max = decMax.Neg(), decMax.Sub(dec.One) - case DataTypeMajorUint, - DataTypeMajorFixedBytes: - bigUMax := new(big.Int).Lsh(bigIntOne, (uint(minor)+1)*8) - max = decimal.NewFromBigInt(bigUMax, 0).Sub(dec.One) - default: - err = se.ErrorCodeGetMinMax - return - } - - decPairMap[dt] = decPair{Max: max, Min: min} - return -} - // DecimalToUint64 convert decimal to uint64. // Negative case will return error, and decimal part will be trancated. func DecimalToUint64(d decimal.Decimal) (uint64, error) { |