Repository: matrixorigin/matrixone
Pull request #4483 (2022-08-12 08:19:16)

add cast decimal128 as int32 and fix func of floor
## What type of PR is this?

- [ ] API-change
- [ ] BUG
- [ ] Improvement
- [ ] Documentation
- [ ] Feature
- [ ] Test and CI
- [ ] Code Refactoring

## Which issue(s) this PR fixes:

issue #3219

## What this PR does / why we need it:


Patch:
diff --git a/pkg/sql/plan/function/builtin/binary/typecast.go b/pkg/sql/plan/function/builtin/binary/typecast.go
index dc23814ab..294cb9589 100644
--- a/pkg/sql/plan/function/builtin/binary/typecast.go
+++ b/pkg/sql/plan/function/builtin/binary/typecast.go
@@ -550,6 +550,24 @@ func Decimal128ToInt64(xs []types.Decimal128, scale int32, rs []int64) ([]int64,
 	return rs, nil
 }
 
+func Decimal128ToInt32(xs []types.Decimal128, scale int32, rs []int32) ([]int32, error) {
+	for i, x := range xs {
+		xStr := x.ToStringWithScale(scale)
+		floatRepresentation, err := strconv.ParseFloat(xStr, 64)
+		if err != nil {
+			return []int32{}, moerr.NewError(moerr.OUT_OF_RANGE, "cannot convert decimal to INT correctly")
+		}
+
+		if floatRepresentation > math.MaxInt32 || floatRepresentation < math.MinInt32 {
+			return []int32{}, moerr.NewError(moerr.OUT_OF_RANGE, "cannot convert decimal to INT correctly")
+		}
+
+		result := int32(math.Round(floatRepresentation))
+		rs[i] = result
+	}
+	return rs, nil
+}
+
 func Decimal64ToUint64(xs []types.Decimal64, scale int32, rs []uint64) ([]uint64, error) {
 	for i, x := range xs {
 		xStr := x.ToStringWithScale(scale)
diff --git a/pkg/sql/plan/function/builtin/multi/floor.go b/pkg/sql/plan/function/builtin/multi/floor.go
index 8c6f32a4e..ed54dc4cc 100644
--- a/pkg/sql/plan/function/builtin/multi/floor.go
+++ b/pkg/sql/plan/function/builtin/multi/floor.go
@@ -195,3 +195,28 @@ func FloorFloat64Int64(vecs []*vector.Vector, proc *process.Process) (*vector.Ve
 		return vec, nil
 	}
 }
+
+func FloorDecimal128(vecs []*vector.Vector, proc *process.Process) (*vector.Vector, error) {
+	digits := int64(0)
+	vs := vector.MustTCols[types.Decimal128](vecs[0])
+	if vecs[0].IsScalar() {
+		if vecs[0].IsScalarNull() {
+			return proc.AllocScalarNullVector(types.Type{Oid: types.T_decimal128, Size: 16}), nil
+		}
+		vec := proc.AllocScalarVector(types.Type{Oid: types.T_decimal128, Size: 16})
+		rs := make([]types.Decimal128, 1)
+		nulls.Set(vec.Nsp, vecs[0].Nsp)
+		vector.SetCol(vec, floor.FloorDecimal128(vs, rs, digits))
+		return vec, nil
+	} else {
+		vec, err := proc.AllocVector(types.Type{Oid: types.T_decimal128, Size: 16}, 16*int64(len(vs)))
+		if err != nil {
+			return nil, err
+		}
+		rs := encoding.DecodeDecimal128Slice(vec.Data)
+		rs = rs[:len(vs)]
+		nulls.Set(vec.Nsp, vecs[0].Nsp)
+		vector.SetCol(vec, floor.FloorDecimal128(vs, rs, digits))
+		return vec, nil
+	}
+}
diff --git a/pkg/sql/plan/function/builtins.go b/pkg/sql/plan/function/builtins.go
index ed7afb016..245d24864 100644
--- a/pkg/sql/plan/function/builtins.go
+++ b/pkg/sql/plan/function/builtins.go
@@ -744,6 +744,13 @@ var builtins = map[int]Functions{
 				Args:      []types.T{types.T_float64, types.T_int64},
 				ReturnTyp: types.T_float64, Fn: multi.FloorFloat64Int64,
 			},
+			{
+				Index:     6,
+				Flag:      plan.Function_STRICT,
+				Layout:    STANDARD_FUNCTION,
+				Args:      []types.T{types.T_decimal128},
+				ReturnTyp: types.T_decimal128, Fn: multi.FloorDecimal128,
+			},
 		},
 	},
 	LPAD: {
diff --git a/pkg/sql/plan/function/operator/cast.go b/pkg/sql/plan/function/operator/cast.go
index 7c2e06546..83f333dcc 100644
--- a/pkg/sql/plan/function/operator/cast.go
+++ b/pkg/sql/plan/function/operator/cast.go
@@ -588,6 +588,9 @@ func doCast(vs []*vector.Vector, proc *process.Process) (*vector.Vector, error)
 	if lv.Typ.Oid == types.T_decimal64 && rv.Typ.Oid == types.T_int64 {
 		return CastDecimal64ToInt64(lv, rv, proc)
 	}
+	if lv.Typ.Oid == types.T_decimal128 && rv.Typ.Oid == types.T_int32 {
+		return CastDecimal128ToInt32(lv, rv, proc)
+	}
 	if lv.Typ.Oid == types.T_decimal128 && rv.Typ.Oid == types.T_int64 {
 		return CastDecimal128ToInt64(lv, rv, proc)
 	}
@@ -2280,6 +2283,33 @@ func CastDecimal128ToInt64(lv, rv *vector.Vector, proc *process.Process) (*vecto
 	return vec, nil
 }
 
+func CastDecimal128ToInt32(lv, rv *vector.Vector, proc *process.Process) (*vector.Vector, error) {
+	rtl := 4
+	lvs := lv.Col.([]types.Decimal128)
+	if lv.IsScalar() {
+		vec := proc.AllocScalarVector(rv.Typ)
+		rs := make([]int32, 1)
+		if _, err := binary.Decimal128ToInt32(lvs, lv.Typ.Scale, rs); err != nil {
+			return nil, err
+		}
+		nulls.Set(vec.Nsp, lv.Nsp)
+		vector.SetCol(vec, rs)
+		return vec, nil
+	}
+	vec, err := proc.AllocVector(rv.Typ, int64(len(lvs)*rtl))
+	if err != nil {
+		return nil, err
+	}
+	rs := encoding.DecodeInt32Slice(vec.Data)
+	rs = rs[:len(lvs)]
+	if _, err := binary.Decimal128ToInt32(lvs, lv.Typ.Scale, rs); err != nil {
+		return nil, err
+	}
+	nulls.Set(vec.Nsp, lv.Nsp)
+	vector.SetCol(vec, rs)
+	return vec, nil
+}
+
 func CastNumValToBool[T constraints.Integer | constraints.Float](lv, rv *vector.Vector, proc *process.Process) (*vector.Vector, error) {
 	rtl := 8
 	lvs := vector.MustTCols[T](lv)
diff --git a/pkg/sql/plan/function/operators.go b/pkg/sql/plan/function/operators.go
index 4749c2ec7..bd9b1b13f 100644
--- a/pkg/sql/plan/function/operators.go
+++ b/pkg/sql/plan/function/operators.go
@@ -4816,6 +4816,14 @@ var operators = map[int]Functions{
 				ReturnTyp: types.T_json,
 				Fn:        operator.Cast,
 			},
+			{
+				Index:     265,
+				Flag:      plan.Function_STRICT,
+				Layout:    CAST_EXPRESSION,
+				Args:      []types.T{types.T_decimal128, types.T_int32},
+				ReturnTyp: types.T_json,
+				Fn:        operator.Cast,
+			},
 		},
 	},
 
diff --git a/pkg/vectorize/floor/floor.go b/pkg/vectorize/floor/floor.go
index f3194f6a5..69af26e30 100644
--- a/pkg/vectorize/floor/floor.go
+++ b/pkg/vectorize/floor/floor.go
@@ -34,21 +34,23 @@ N >= 0, floor to the Nth placeholder after decimal point
 */
 
 import (
-	"fmt"
+	"github.com/matrixorigin/matrixone/pkg/container/types"
 	"math"
+	"strings"
 )
 
 var (
-	FloorUint8   func([]uint8, []uint8, int64) []uint8
-	FloorUint16  func([]uint16, []uint16, int64) []uint16
-	FloorUint32  func([]uint32, []uint32, int64) []uint32
-	FloorUint64  func([]uint64, []uint64, int64) []uint64
-	FloorInt8    func([]int8, []int8, int64) []int8
-	FloorInt16   func([]int16, []int16, int64) []int16
-	FloorInt32   func([]int32, []int32, int64) []int32
-	FloorInt64   func([]int64, []int64, int64) []int64
-	FloorFloat32 func([]float32, []float32, int64) []float32
-	FloorFloat64 func([]float64, []float64, int64) []float64
+	FloorUint8      func([]uint8, []uint8, int64) []uint8
+	FloorUint16     func([]uint16, []uint16, int64) []uint16
+	FloorUint32     func([]uint32, []uint32, int64) []uint32
+	FloorUint64     func([]uint64, []uint64, int64) []uint64
+	FloorInt8       func([]int8, []int8, int64) []int8
+	FloorInt16      func([]int16, []int16, int64) []int16
+	FloorInt32      func([]int32, []int32, int64) []int32
+	FloorInt64      func([]int64, []int64, int64) []int64
+	FloorFloat32    func([]float32, []float32, int64) []float32
+	FloorFloat64    func([]float64, []float64, int64) []float64
+	FloorDecimal128 func([]types.Decimal128, []types.Decimal128, int64) []types.Decimal128
 )
 
 var MaxUint8digits = numOfDigits(math.MaxUint8)
@@ -104,6 +106,7 @@ func init() {
 	FloorInt64 = floorInt64
 	FloorFloat32 = floorFloat32
 	FloorFloat64 = floorFloat64
+	FloorDecimal128 = floorDecimal128
 }
 
 func floorUint8(xs, rs []uint8, digits int64) []uint8 {
@@ -279,7 +282,6 @@ func floorFloat64(xs, rs []float64, digits int64) []float64 {
 		for i := range xs {
 			rs[i] = math.Floor(xs[i])
 		}
-		fmt.Println(digits)
 	} else {
 		scale := math.Pow10(int(digits))
 		for i := range xs {
@@ -289,3 +291,16 @@ func floorFloat64(xs, rs []float64, digits int64) []float64 {
 	}
 	return rs
 }
+
+func floorDecimal128(xs, rs []types.Decimal128, _ int64) []types.Decimal128 {
+	for i := range xs {
+		str := strings.Split(xs[i].String(), ".")[0]
+		x, _ := types.Decimal128_FromString(str)
+		if str[0] != '-' {
+			rs[i] = x
+			continue
+		}
+		rs[i] = x.AddInt64(-1)
+	}
+	return rs
+}


Test patch:
diff --git a/test/cases/function/func_math_floor.test b/test/cases/function/func_math_floor.test
index 6d0b9fa21..9ae61a8cb 100644
--- a/test/cases/function/func_math_floor.test
+++ b/test/cases/function/func_math_floor.test
@@ -22,14 +22,8 @@ DROP TABLE t1;
 #EXTREME VALUE
 
 select floor(999999999999999999);
-
--- @bvt:issue#3588
 select floor(9999999999999999999999);
--- @bvt:issue
-
--- @bvt:issue#3579
 select floor(9.999999999999999999999);
--- @bvt:issue
 
 
 select floor(-9.999999999999999999999);