Repository: pingcap/tidb (Go)

Issue:
aggregation functions on datatype `year` not work well
## Bug Report

### 1. What did you do?
In standalone TiDB (without TiKV)
```sql
mysql root@127.0.0.1:test> create table t (y year);                             
Query OK, 0 rows affected
Time: 0.011s
mysql root@127.0.0.1:test> insert into t values (2000), (2010), (2020);         
Query OK, 3 rows affected
Time: 0.003s
mysql root@127.0.0.1:test> select sum(y) from t;                                
+-----------------------+
| sum(y)                |
+-----------------------+
| 1.27956346195226e-310 |
+-----------------------+
1 row in set
Time: 0.016s
mysql root@127.0.0.1:test> select avg(y) from t;                                
+----------------------+
| avg(y)               |
+----------------------+
| 4.2652115398407e-311 |
+----------------------+
1 row in set
Time: 0.018s
```

With TiKV:
```sql
mysql root@localhost:test> create table t (y year);                                                                                                                                                                                                                                       
Query OK, 0 rows affected
Time: 0.102s
mysql root@localhost:test> insert into t values (2000), (2010), (2020);                                                                                                                                                                                                                   
Query OK, 3 rows affected
Time: 0.023s
mysql root@localhost:test> select sum(y) from t;                                                                                                                                                                                                                                          
(1105, u'other error: [components/tidb_query_vec_aggr/src/impl_sum.rs:47]: Unexpected return field type Double')
mysql root@localhost:test> select avg(y) from t;                                                                                                                                                                                                                                          
(1105, u'other error: [components/tidb_query_vec_aggr/src/impl_sum.rs:47]: Unexpected return field type Double')
```

### 2. What did you expect to see?
In MySQL 5.7
```sql
mysql root@127.0.0.1:test> create table t (y year);                             
Query OK, 0 rows affected
Time: 0.287s
mysql root@127.0.0.1:test> insert into t values (2020), (2000), (2050);         
Query OK, 3 rows affected
Time: 0.048s
mysql root@127.0.0.1:test> select avg(y) from t;                                
+-----------+
| avg(y)    |
+-----------+
| 2023.3333 |
+-----------+
1 row in set
Time: 0.017s
mysql root@127.0.0.1:test> select sum(y) from t;                                
+--------+
| sum(y) |
+--------+
| 6070   |
+--------+
1 row in set
Time: 0.016s
```


### 3. What version of TiDB are you using? (`tidb-server -V` or run `select tidb_version();` on TiDB)
```sql
mysql root@localhost:test> select tidb_version();                                                                                                                                                                                                                                         
+-------------------------------------------------------------------+
| tidb_version()                                                    |
+-------------------------------------------------------------------+
| Release Version: v4.0.0-beta.2-90-g7a67ff482                      |
| Git Commit Hash: 7a67ff482b21b7405b582d799215f5ac333fc0ec         |
| Git Branch: master                                                |
| UTC Build Time: 2020-03-26 10:21:51                               |
| GoVersion: go1.13.1                                               |
| Race Enabled: false                                               |
| TiKV Min Version: v3.0.0-60965b006877ca7234adaced7890d7b029ed1306 |
| Check Table Before Drop: false                                    |
+-------------------------------------------------------------------+
1 row in set
Time: 0.012s

```


Discussion:
Hi @SunRunAway, I will work on this.



Patch:
diff --git a/expression/aggregation/base_func.go b/expression/aggregation/base_func.go
index f384a6bcd2f36..8b8e44f0474ca 100644
--- a/expression/aggregation/base_func.go
+++ b/expression/aggregation/base_func.go
@@ -136,7 +136,7 @@ func (a *baseFuncDesc) typeInfer4ApproxCountDistinct(ctx sessionctx.Context) {
 // Because child returns integer or decimal type.
 func (a *baseFuncDesc) typeInfer4Sum(ctx sessionctx.Context) {
 	switch a.Args[0].GetType().Tp {
-	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong:
+	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeYear:
 		a.RetTp = types.NewFieldType(mysql.TypeNewDecimal)
 		a.RetTp.Flen, a.RetTp.Decimal = mysql.MaxDecimalWidth, 0
 	case mysql.TypeNewDecimal:
@@ -159,7 +159,7 @@ func (a *baseFuncDesc) typeInfer4Sum(ctx sessionctx.Context) {
 // Because child returns integer or decimal type.
 func (a *baseFuncDesc) typeInfer4Avg(ctx sessionctx.Context) {
 	switch a.Args[0].GetType().Tp {
-	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeNewDecimal:
+	case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeYear, mysql.TypeNewDecimal:
 		a.RetTp = types.NewFieldType(mysql.TypeNewDecimal)
 		if a.Args[0].GetType().Decimal < 0 {
 			a.RetTp.Decimal = mysql.MaxDecimalScale


Test patch:
diff --git a/executor/aggregate_test.go b/executor/aggregate_test.go
index 1ea40bb63b435..4c9d53d1801af 100644
--- a/executor/aggregate_test.go
+++ b/executor/aggregate_test.go
@@ -1058,3 +1058,13 @@ func (s *testSuiteAgg) TestIssue15690(c *C) {
 	tk.MustQuery(`select /*+ stream_agg() */ distinct * from t;`).Check(testkit.Rows("<nil>", "a", "b"))
 	c.Assert(tk.Se.GetSessionVars().StmtCtx.WarningCount(), Equals, uint16(0))
 }
+
+func (s *testSuiteAgg) TestIssue15958(c *C) {
+	tk := testkit.NewTestKitWithInit(c, s.store)
+	tk.Se.GetSessionVars().MaxChunkSize = 2
+	tk.MustExec(`drop table if exists t;`)
+	tk.MustExec(`create table t(y year);`)
+	tk.MustExec(`insert into t values (2020), (2000), (2050);`)
+	tk.MustQuery(`select sum(y) from t`).Check(testkit.Rows("6070"))
+	tk.MustQuery(`select avg(y) from t`).Check(testkit.Rows("2023.3333"))
+}