matrixorigin / matrixorigin/matrixone
[Bug]: EXPORT_SET misinterprets DECIMAL and truncates FLOAT bit masks
- Dominant language
- Go
- Stars
- 1.9k
- Forks
- 311
- Avg merge
- 1d 3h
- Merged PRs (30d)
- 768
Description
### Is there an existing issue for the same bug?
- [x] I have checked the existing issues.
- #28210 concerns an INT `number_of_bits` column.
- #28211 concerns zero/negative `number_of_bits` boundaries.
- #28399 covers DECIMAL handling in `MAKE_SET`.
No existing issue covers the first `bits` argument of `EXPORT_SET()`.
### Branch Name
main
### Commit ID
`a9d3b8b857c44f1249e682c91d4d62a914eb7d20`
### Other Environment Information
- Local standalone MatrixOne built from the commit above
- Reference: MySQL 8.3.0
### Actual Behavior
`EXPORT_SET(bits, ...)` uses different and incorrect conversions for DECIMAL, FLOAT/DOUBLE, BOOL, and prepared values.
#### DECIMAL storage is used as an unscaled bit mask
```sql
SELECT
EXPORT_SET(CAST(1.4 AS DECIMAL(4,1)),'Y','N','',4),
EXPORT_SET(CAST(1.40 AS DECIMAL(4,2)),'Y','N','',4),
EXPORT_SET(CAST(1.400 AS DECIMAL(5,3)),'Y','N','',4);
```
```text
MatrixOne: NYYY, NNYY, NNNY
MySQL: YNNN, YNNN, YNNN
```
The MatrixOne results correspond to masks 14, 140, and 1400: the stored DECIMAL coefficients. Merely changing scale changes the selected bits.
#### FLOAT/DOUBLE values are truncated instead of rounded
For DOUBLE values 1.4, 1.5, 1.9, and -1.5, MatrixOne uses masks 1, 1, 1, and -1. MySQL uses 1, 2, 2, and -2. This changes both positive and negative selected-bit results.
#### Boolean inputs are rejected
`EXPORT_SET(TRUE,'Y','N','',4)` is rejected with `invalid argument function export_set`; MySQL returns `YNNN`.
#### Prepared values lose their numeric category
With a fresh server-side statement on every run, DECIMAL/DOUBLE 1.5 produces `YNNN` in MatrixOne and `NYNN` in MySQL. TRUE produces `NNNN` in MatrixOne and `YNNN` in MySQL.
All scalar, column, CTAS, and prepared forms were reproduced three times.
The executor confirms the observed split:
- FLOAT/DOUBLE getters call `int64(val)`, which truncates.
- Other accepted numeric types fall through to `GenerateFunctionFixedTypeParameter[int64]`; DECIMAL storage is then read without applying its scale.
- The checker has no accepted Boolean numeric path.
### Expected Behavior
The first `bits` argument should be converted to an integer numeric value before bit inspection. Equivalent DECIMAL values must be scale-invariant, fractional numeric values must follow MySQL's rounding rule for this argument, and Boolean values must map to 0/1.
### Steps to Reproduce
```sql
CREATE DATABASE codex_export_set_bits;
USE codex_export_set_bits;
CREATE TABLE t(
id INT PRIMARY KEY,
d1 DECIMAL(4,1),
d2 DECIMAL(5,2),
f DOUBLE,
b BOOLEAN
);
INSERT INTO t VALUES
(1,1.4,1.40,1.4,TRUE),
(2,1.5,1.50,1.5,FALSE),
(3,1.9,1.90,1.9,NULL),
(4,-1.5,-1.50,-1.5,NULL);
SELECT id,EXPORT_SET(d1,'Y','N','',4) FROM t ORDER BY id;
SELECT id,EXPORT_SET(d2,'Y','N','',4) FROM t ORDER BY id;
SELECT id,EXPORT_SET(f,'Y','N','',4) FROM t ORDER BY id;
SELECT id,EXPORT_SET(b,'Y','N','',4) FROM t ORDER BY id;
```
### Controls
- Integer masks 0, 1, 2, 3, and -1 agree with MySQL.
- NULL propagation remains correct.
- `number_of_bits` behavior is not part of this issue and remains tracked by #28210/#28211.
Contributor guide
Assessment
This issue has not been assessed yet.