Skip to content
Open
Show file tree
Hide file tree
Changes from 6 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
f1b5f89
fix: reimplement MySQL type compatibility for 3.0-dev
ck89119 Apr 26, 2026
d603b97
fix: address mysql compatibility review gaps
ck89119 Apr 26, 2026
c8efdb5
fix: address decimal256 CI failures
ck89119 Apr 27, 2026
cf8d4a9
fix: complete mysql compatibility review fixes
ck89119 Apr 27, 2026
72fd9c6
fix: address round-2 review gaps for MySQL type compatibility
ck89119 Apr 27, 2026
96d5c50
fix: address round-3 review gaps for MySQL type compatibility
ck89119 Apr 27, 2026
0dc82b2
fix: align array-scalar float overflow error type with array-array path
ck89119 Apr 27, 2026
49725ce
fix: update BVT result files for float array overflow and decimal sca…
ck89119 Apr 27, 2026
ee5780f
fix: update BVT result files for decimal scale limit and decimal256 f…
ck89119 Apr 27, 2026
903fba0
fix: report user-visible column name in unique-index duplicate entry …
ck89119 Apr 27, 2026
ba3d947
fix: propagate parent unique column name to fuzzy filter operator
ck89119 Apr 27, 2026
f28859a
fix: rewrite __mo_index_idx_col to user-visible name in duplicate ent…
ck89119 Apr 27, 2026
d29cb1f
fix: write back SET-aware expression in default / on update
ck89119 Apr 28, 2026
c3d5f86
fix: split fuzzyCheck attr into SQL-side attr and display-side displa…
ck89119 Apr 28, 2026
e24d7b0
fix: restore BVT placeholders for issue#8516/8513 decimal oracles
ck89119 Apr 28, 2026
420d4b6
fix: tighten Decimal64 scientific notation to match Decimal128/256
ck89119 Apr 28, 2026
cbccfe4
fix: parse numeric SET fallback as base-10 instead of Go base-0
ck89119 Apr 28, 2026
d375ab0
fix: reject signed and 3-digit YEAR literals in ParseMoYear
ck89119 Apr 28, 2026
6101024
fix: skip duplicate-entry rewrite when target table has multiple uniq…
ck89119 Apr 28, 2026
b58c803
fix: resolve SET default / on-update before the generic cast wrapper
ck89119 Apr 28, 2026
2d24983
fix: round float values when casting to YEAR before range check
ck89119 Apr 28, 2026
3f3af7d
fix: only NUL-trim BINARY fixed-length payload when casting to YEAR
ck89119 Apr 28, 2026
9107676
fix: guard scientific-notation exponent against int32 overflow
ck89119 Apr 28, 2026
4432c30
fix: hook duplicate-entry rewrite at the statement boundary, not just…
ck89119 Apr 28, 2026
2a11f0f
Merge remote-tracking branch 'mo/3.0-dev' into issue-24184-v2
ck89119 Apr 28, 2026
b73c18c
fix: update Optimistic BVT results to expect user-visible dup key names
ck89119 Apr 28, 2026
f4fbb01
test: expand UT coverage for SET, YEAR, Decimal, and float overflow h…
ck89119 Apr 28, 2026
33b9326
test: broaden UT coverage on touched files for the 75% coverage gate
ck89119 Apr 28, 2026
f25fdff
Merge remote-tracking branch 'mo/3.0-dev' into issue-24184-v2
ck89119 Apr 28, 2026
e93f647
Merge remote-tracking branch 'mo/3.0-dev' into issue-24184-v2
ck89119 Apr 28, 2026
cc77b0a
Merge remote-tracking branch 'mo/3.0-dev' into issue-24184-v2
ck89119 Apr 29, 2026
772d149
fix: surface composite hidden unique index name in duplicate-entry er…
ck89119 Apr 29, 2026
31a93fc
fix: preserve SET member case and verbatim non-literal default in SHO…
ck89119 Apr 29, 2026
642126d
fix: parse decimal-to-float once at target precision; expand decimal2…
ck89119 Apr 29, 2026
4daf5c6
fix: don't retry malformed decimal literals against Decimal256
ck89119 Apr 29, 2026
2745fd4
docs: annotate review-flagged compromises with follow-up notes
ck89119 Apr 29, 2026
1958330
Merge remote-tracking branch 'mo/3.0-dev' into issue-24184-v2
ck89119 Apr 29, 2026
111f7c4
fix: restore double-parse in decimal-to-float to preserve float(W,S) …
ck89119 Apr 29, 2026
124e6b3
fix: cover composite hidden UNIQUE dup-entry in RewriteHiddenIndexDup…
ck89119 Apr 30, 2026
98b1ab4
fix: reject finite-to-Inf silent overflow in moarray.Cast
ck89119 Apr 30, 2026
789a395
fix: split formatStr in SHOW CREATE; preserve DEFAULT exprs and escap…
ck89119 Apr 30, 2026
176b57f
fix: tighten float cast range/NaN checks for float->float, ->integer,…
ck89119 Apr 30, 2026
78e6a05
fix: hide internal hidden-index column name in fuzzyCheck onlyInsertH…
ck89119 Apr 30, 2026
fc44dcf
fix: escape single quotes in SHOW CREATE EXTERNAL TABLE string literals
ck89119 Apr 30, 2026
a53289a
fix: stop double-escaping column/table comments in SHOW CREATE
ck89119 Apr 30, 2026
59f2533
test: lift PR-diff coverage past the 75% gate
ck89119 Apr 30, 2026
75ed20f
fix: close float64 imprecision hole near MaxInt64/MaxUint64 in cast
ck89119 Apr 30, 2026
fcf2ac9
fix: hide internal hidden-index column name in constructFuzzyFilter f…
ck89119 Apr 30, 2026
3f567a8
fix: escape backslashes in SHOW CREATE string literals
ck89119 Apr 30, 2026
9b63779
fix: close 6 remaining correctness holes
ck89119 May 6, 2026
ece3a52
fix: close 4 remaining correctness holes (round 2)
ck89119 May 6, 2026
9735723
fix: unsized ARRAY cast and isSameColumnType equality (round 3)
ck89119 May 6, 2026
8967769
test: update BVT result for comment backslash escaping
ck89119 May 6, 2026
c545837
fix: escape DDL verbatim when wrapping in double-quoted SQL literal
ck89119 May 7, 2026
d4d4eb1
Merge remote-tracking branch 'mo/3.0-dev' into issue-24184-v2
ck89119 May 7, 2026
b31a2a5
fix: close 5 remaining correctness holes (round 4)
ck89119 May 7, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
293 changes: 282 additions & 11 deletions pkg/container/types/decimal.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ import (
"encoding/binary"
"fmt"
"math"
"math/big"
"math/bits"

"github.com/matrixorigin/matrixone/pkg/common/moerr"
Expand Down Expand Up @@ -1498,6 +1499,7 @@ func Parse64(x string) (y Decimal64, scale int32, err error) {
flag := false
t := false
floatflag := false
expDigitSeen := false
scalecount := int32(0)
scalesign := false
signx := false
Expand Down Expand Up @@ -1593,6 +1595,7 @@ func Parse64(x string) (y Decimal64, scale int32, err error) {
scale++
}
} else {
expDigitSeen = true
scalecount = scalecount*10 + int32(x[i]-'0')
}
i++
Expand All @@ -1601,6 +1604,10 @@ func Parse64(x string) (y Decimal64, scale int32, err error) {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal64.", x)
return
}
if floatflag && !expDigitSeen {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal64.", x)
return
}
if scale == -1 {
scale = 0
}
Expand Down Expand Up @@ -1690,15 +1697,19 @@ func Parse128(x string) (y Decimal128, scale int32, err error) {
i := 0
flag := false
floatflag := false
expDigitSeen := false
scalecount := int32(0)
scalesign := false
signx := false
if x[0] == '-' {
for i < len(x) && x[i] == ' ' {
i++
}
if i < len(x) && (x[i] == '-' || x[i] == '+') {
signx = x[i] == '-'
i++
signx = true
}
for i < len(x) {
if x[i] == ' ' || x[i] == '+' {
if x[i] == ' ' {
i++
continue
}
Expand Down Expand Up @@ -1741,14 +1752,17 @@ func Parse128(x string) (y Decimal128, scale int32, err error) {
return
}
} else if x[i] < '0' || x[i] > '9' {
if x[i] == 'e' {
if x[i] == 'e' || x[i] == 'E' {
if floatflag {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal128.", x)
return
}
floatflag = true
i++
continue
}
if x[i] == '-' && floatflag {
scalesign = true
i++
if i < len(x) && (x[i] == '-' || x[i] == '+') {
scalesign = x[i] == '-'
i++
}
continue
}
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal128.", x)
Expand Down Expand Up @@ -1782,6 +1796,7 @@ func Parse128(x string) (y Decimal128, scale int32, err error) {
scale++
}
} else {
expDigitSeen = true
scalecount = scalecount*10 + int32(x[i]-'0')
}
i++
Expand All @@ -1790,6 +1805,10 @@ func Parse128(x string) (y Decimal128, scale int32, err error) {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal128.", x)
return
}
if floatflag && !expDigitSeen {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal128.", x)
return
}
if scale == -1 {
scale = 0
}
Expand All @@ -1812,6 +1831,157 @@ func Parse128(x string) (y Decimal128, scale int32, err error) {
return
}

func Parse256(x string) (y Decimal256, scale int32, err error) {
if x == "" {
return Decimal256{}, 0, moerr.NewInvalidInputNoCtx("can't cast empty string to Decimal256")
}
var z Decimal256
width := 0
t := false
scale = -1
i := 0
flag := false
floatflag := false
expDigitSeen := false
scalecount := int32(0)
scalesign := false
signx := false
for i < len(x) && x[i] == ' ' {
i++
}
if i < len(x) && (x[i] == '-' || x[i] == '+') {
signx = x[i] == '-'
i++
}
for i < len(x) {
if x[i] == ' ' {
i++
continue
}
if x[i] == 'x' && i != 0 && x[i-1] == '0' &&
y.B0_63 == 0 && y.B64_127 == 0 && y.B128_191 == 0 && y.B192_255 == 0 {
t = true
i++
continue
}
if t {
if (x[i] >= '0' && x[i] <= '9') || (x[i] >= 'a' && x[i] <= 'f') || (x[i] >= 'A' && x[i] <= 'F') {
xx := uint64(0)
if x[i] >= '0' && x[i] <= '9' {
xx = uint64(x[i] - '0')
} else if x[i] >= 'a' && x[i] <= 'f' {
xx = uint64(x[i]-'a') + 10
} else {
xx = uint64(x[i]-'A') + 10
}
flag = true
z, err = y.Mul256(Decimal256{16, 0, 0, 0})
if err == nil {
y, err = z.Add256(Decimal256{xx, 0, 0, 0})
}
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256.", x)
return
}
} else {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal256.", x)
return
}
i++
continue
}
if x[i] == '.' {
if scale == -1 {
scale = 0
} else {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal256.", x)
return
}
} else if x[i] < '0' || x[i] > '9' {
if x[i] == 'e' || x[i] == 'E' {
if floatflag {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal256.", x)
return
}
floatflag = true
i++
if i < len(x) && (x[i] == '-' || x[i] == '+') {
scalesign = x[i] == '-'
i++
}
continue
}
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal256.", x)
return
} else if !floatflag {
if width == 76 {
if scale == -1 {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256.", x)
return
}
if x[i] >= '5' {
y, err = y.Add256(Decimal256{1, 0, 0, 0})
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256.", x)
return
}
y1, _ := y.Mod256(Decimal256{10, 0, 0, 0})
if y1.B0_63 == 0 && y1.B64_127 == 0 && y1.B128_191 == 0 && y1.B192_255 == 0 {
scale--
y, _ = y.Scale(-1)
}
}
break
}
flag = true
z, err = y.Mul256(Decimal256{Pow10[1], 0, 0, 0})
if err == nil {
y, err = z.Add256(Decimal256{uint64(x[i] - '0'), 0, 0, 0})
}
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256.", x)
return
}
width++
if scale != -1 {
scale++
}
} else {
expDigitSeen = true
scalecount = scalecount*10 + int32(x[i]-'0')
}
i++
}
if !flag {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal256.", x)
return
}
if floatflag && !expDigitSeen {
err = moerr.NewInvalidInputNoCtxf("%s is illegal string, can't be converted to Decimal256.", x)
return
}
if scale == -1 {
scale = 0
}
if floatflag {
if scalesign {
scalecount = -scalecount
}
scale -= scalecount
if scale < 0 {
y, err = y.Scale(-scale)
scale = 0
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256.", x)
}
}
}
if signx {
y = y.Minus()
}
return
}

func ParseDecimal128(x string, width, scale int32) (y Decimal128, err error) {
if x == "" {
return Decimal128{0, 0}, moerr.NewInvalidInputNoCtx("can't cast empty string to Decimal128")
Expand Down Expand Up @@ -1854,6 +2024,84 @@ func ParseDecimal128(x string, width, scale int32) (y Decimal128, err error) {
return
}

func decimal256Pow10(width int32) (Decimal256, error) {
result := Decimal256{1, 0, 0, 0}
for width > 19 {
next, err := result.Mul256(Decimal256{Pow10[19], 0, 0, 0})
if err != nil {
return Decimal256{}, err
}
result = next
width -= 19
}
if width > 0 {
next, err := result.Mul256(Decimal256{Pow10[width], 0, 0, 0})
if err != nil {
return Decimal256{}, err
}
result = next
}
return result, nil
}

func ParseDecimal256(x string, width, scale int32) (y Decimal256, err error) {
if x == "" {
return Decimal256{}, moerr.NewInvalidInputNoCtx("can't cast empty string to Decimal256")
}
if width > 76 {
width = 76
}
n := int32(0)
y, n, err = Parse256(x)
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256(%d,%d).", x, width, scale)
return
}
if n > scale {
y, _ = y.Scale(scale - n)
} else {
y, err = y.Scale(scale - n)
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256(%d,%d).", x, width, scale)
return
}
}
z, err := decimal256Pow10(width)
if err != nil {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256(%d,%d).", x, width, scale)
return
}
if y.Sign() {
if y.Less(z.Minus()) {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256(%d,%d).", x, width, scale)
return
}
} else if !y.Less(z) {
err = moerr.NewInvalidInputNoCtxf("%s beyond the range, can't be converted to Decimal256(%d,%d).", x, width, scale)
return
}
return
}

func ParseDecimal256FromByte(x string, width, scale int32) (y Decimal256, err error) {
if x == "" {
return Decimal256{}, moerr.NewInvalidInputNoCtx("can't cast empty string to Decimal256")
}
y = Decimal256{}
n := len(x)
for i := 0; i < n; i++ {
y, err = y.Mul256(Decimal256{256, 0, 0, 0})
if err != nil {
return
}
y, err = y.Add256(Decimal256{uint64(x[i]), 0, 0, 0})
if err != nil {
return
}
}
return
}

func ParseDecimal128FromByte(x string, width, scale int32) (y Decimal128, err error) {
if x == "" {
return Decimal128{0, 0}, moerr.NewInvalidInputNoCtx("can't cast empty string to Decimal128")
Expand Down Expand Up @@ -1939,8 +2187,31 @@ func (x Decimal128) Format(scale int32) string {
}

func (x Decimal256) Format(scale int32) string {
a := ""
return a
signx := x.Sign()
if signx {
x = x.Minus()
}

n := new(big.Int).SetUint64(x.B192_255)
n.Lsh(n, 64)
n.Add(n, new(big.Int).SetUint64(x.B128_191))
n.Lsh(n, 64)
n.Add(n, new(big.Int).SetUint64(x.B64_127))
n.Lsh(n, 64)
n.Add(n, new(big.Int).SetUint64(x.B0_63))

s := n.String()
if scale > 0 {
for int32(len(s)) <= scale {
s = "0" + s
}
pos := len(s) - int(scale)
s = s[:pos] + "." + s[pos:]
}
if signx && s != "0" {
s = "-" + s
}
return s
}

func (x Decimal64) Ceil(scale1, scale2 int32, isConst bool) Decimal64 {
Expand Down
Loading
Loading