matrixorigin / matrixorigin/matrixone

[Compatibility]: SUM and AVG reject ENUM and SET numeric aggregation supported by MySQL

Open
#28,692 0 comments 0 reactions 1 assignee Claimed by @XuPeng-SH View on GitHub
kind/bug needs-triage
Dominant language
Go
Stars
1.9k
Forks
311
Avg merge
1d 3h
Merged PRs (30d)
768

Description

## 问题描述

MatrixOne 的 `SUM`/`AVG` 类型检查拒绝 `ENUM` 和 `SET` 列,错误把操作数报告为 `VARCHAR`。MySQL 在数值聚合上下文中使用 `ENUM` 的 1-based ordinal 和 `SET` 的 bitmap 数值,因此直接聚合、`DISTINCT` 聚合和分组聚合都可执行。

MatrixOne 对同一列显式增加 `+0` 后能够得到与 MySQL 相同的数值结果,说明存储的 ordinal/bitmap 信息可用,缺口位于直接聚合的类型归一化,而不是数据内容无法表示。

## 环境

- MatrixOne 最新 main:`7013fbbd6e152ba31da2d3dbba7012ac7f8b8462`
- MatrixOne:本地 launch `2 CN / 1 TN / 1 Log`,全新数据目录
- 对照:MySQL `8.3.0`
- 双方 SQL mode 均含 `STRICT_TRANS_TABLES` 与 `ONLY_FULL_GROUP_BY`

## 最小复现

```sql
create table t(
id int primary key,
g int,
e enum('red','green','blue'),
s set('a','b','c')
);

insert into t values
(1,1,'red','a'),
(2,1,'red','a'),
(3,1,'green','a,b'),
(4,2,'blue','c'),
(5,2,null,null);

select sum(e), avg(e), sum(s), avg(s) from t;
select sum(distinct e), avg(distinct e),
sum(distinct s), avg(distinct s) from t;
select g, sum(e), avg(e), sum(s), avg(s)
from t group by g order by g;
```

## MatrixOne 行为

上述查询在绑定阶段被拒绝:

```text
ERROR 20203 (HY000): invalid argument aggregate function sum, bad value [VARCHAR]
ERROR 20203 (HY000): invalid argument aggregate function avg, bad value [VARCHAR]
```

直接、`DISTINCT` 和分组形式均如此,连续执行三轮结果一致。

## MySQL 行为

```text
sum(e) avg(e) sum(s) avg(s)
7 1.75 9 2.25

sum(distinct e) avg(distinct e) sum(distinct s) avg(distinct s)
6 2 8 2.6666666666666665

g sum(e) avg(e) sum(s) avg(s)
1 4 1.3333333333333333 5 1.6666666666666667
2 3 3 4 4
```

## MatrixOne 数值对照

```sql
select sum(e+0), avg(e+0),
sum(distinct e+0), avg(distinct e+0) from t;
-- 7, 1.7500, 6, 2.0000

select sum(s+0), avg(s+0),
sum(distinct s+0), avg(distinct s+0) from t;
-- 9, 2.2500, 8, 2.6667
```

显式数值化后的值与 MySQL 一致。

## 期望行为

为了兼容 MySQL,`SUM`/`AVG` 应在数值聚合上下文中将 `ENUM` 转为 ordinal、将 `SET` 转为 bitmap 数值,并对普通、`DISTINCT`、分组、VIEW/CTAS 使用一致规则;不应要求应用额外写 `+0`。

## 初步代码定位

- `pkg/sql/plan/function/list_agg.go` 的 `SumSupportedTypes` 不包含 `T_enum`,`SET` 在当前表示中进入该检查时表现为字符串类型。
- 二元数值运算的 `fixedTypeCastRule1` 已对 `T_enum` 显式按 `uint16` 选择规则,所以 `e+0` 能正确保留 ordinal;`SUM`/`AVG` 的一元聚合检查没有等价的 numeric-context 归一化。
- 该问题与 #28687 不同:#28687 是值经过 `GROUP BY` 输出后再做 `e+0`/`s+0` 时丢失 ordinal/bitmap;本问题在直接聚合绑定阶段发生,不依赖先分组输出。

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.