diff --git a/executor/aggregate.go b/executor/aggregate.go index cf5bf5687e07f..145fd0f7ae2a1 100644 --- a/executor/aggregate.go +++ b/executor/aggregate.go @@ -571,11 +571,24 @@ func getGroupKey(ctx sessionctx.Context, input *chunk.Chunk, groupKey [][]byte, for _, item := range groupByItems { tp := item.GetType() + buf, err := expression.GetColumn(tp.EvalType(), numRows) if err != nil { return nil, err } + // In strict sql mode like ‘STRICT_TRANS_TABLES’,can not insert an invalid enum value like 0. + // While in sql mode like '', can insert an invalid enum value like 0, + // then the enum value 0 will have the enum name '', which maybe conflict with user defined enum ''. + // Ref to issue #26885. + // This check is used to handle invalid enum name same with user defined enum name. + // Use enum value as groupKey instead of enum name. + if item.GetType().GetType() == mysql.TypeEnum { + newTp := *tp + newTp.AddFlag(mysql.EnumSetAsIntFlag) + tp = &newTp + } + if err := expression.EvalExpr(ctx, item, tp.EvalType(), input, buf); err != nil { expression.PutColumn(buf) return nil, err @@ -586,6 +599,7 @@ func getGroupKey(ctx sessionctx.Context, input *chunk.Chunk, groupKey [][]byte, newTp.Flen = 0 tp = &newTp } + groupKey, err = codec.HashGroupKey(ctx.GetSessionVars().StmtCtx, input.NumRows(), buf, groupKey, tp) if err != nil { expression.PutColumn(buf) diff --git a/executor/aggregate_test.go b/executor/aggregate_test.go index 0effc00bd7613..b569526c533a5 100644 --- a/executor/aggregate_test.go +++ b/executor/aggregate_test.go @@ -1529,3 +1529,150 @@ func (s *testSerialSuite) TestAggInDisk(c *C) { tk.MustQuery("select /*+ HASH_AGG() */ count(c) from t;").Check(testkit.Rows("0")) tk.MustQuery("select /*+ HASH_AGG() */ count(c) from t group by c1;").Check(testkit.Rows()) } +<<<<<<< HEAD +======= + +func TestRandomPanicAggConsume(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("set @@tidb_max_chunk_size=32") + tk.MustExec("set @@tidb_init_chunk_size=1") + tk.MustExec("drop table if exists t") + tk.MustExec("create table t(a int)") + for i := 0; i <= 1000; i++ { + tk.MustExec(fmt.Sprintf("insert into t values(%v),(%v),(%v)", i, i, i)) + } + + fpName := "github.com/pingcap/tidb/executor/ConsumeRandomPanic" + require.NoError(t, failpoint.Enable(fpName, "5%panic(\"ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]\")")) + defer func() { + require.NoError(t, failpoint.Disable(fpName)) + }() + + // Test 10 times panic for each AggExec. + var res sqlexec.RecordSet + for i := 1; i <= 10; i++ { + var err error + for err == nil { + // Test paralleled hash agg. + res, err = tk.Exec("select /*+ HASH_AGG() */ count(a) from t group by a") + if err == nil { + _, err = session.GetRows4Test(context.Background(), tk.Session(), res) + require.NoError(t, res.Close()) + } + } + require.EqualError(t, err, "failpoint panic: ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]") + + err = nil + for err == nil { + // Test unparalleled hash agg. + res, err = tk.Exec("select /*+ HASH_AGG() */ count(distinct a) from t") + if err == nil { + _, err = session.GetRows4Test(context.Background(), tk.Session(), res) + require.NoError(t, res.Close()) + } + } + require.EqualError(t, err, "failpoint panic: ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]") + + err = nil + for err == nil { + // Test stream agg. + res, err = tk.Exec("select /*+ STREAM_AGG() */ count(a) from t") + if err == nil { + _, err = session.GetRows4Test(context.Background(), tk.Session(), res) + require.NoError(t, res.Close()) + } + } + require.EqualError(t, err, "failpoint panic: ERROR 1105 (HY000): Out Of Memory Quota![conn_id=1]") + } +} + +func TestIssue35295(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t100") + // This bug only happens on partition prune mode = 'static' + tk.MustExec("set @@tidb_partition_prune_mode = 'static'") + tk.MustExec(`CREATE TABLE t100 ( +ID bigint(20) unsigned NOT NULL AUTO_INCREMENT, +col1 int(10) NOT NULL DEFAULT '0' COMMENT 'test', +money bigint(20) NOT NULL COMMENT 'test', +logtime datetime NOT NULL COMMENT '记录时间', +PRIMARY KEY (ID,logtime) +) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin AUTO_INCREMENT=1 COMMENT='test' +PARTITION BY RANGE COLUMNS(logtime) ( +PARTITION p20220608 VALUES LESS THAN ("20220609"), +PARTITION p20220609 VALUES LESS THAN ("20220610"), +PARTITION p20220610 VALUES LESS THAN ("20220611"), +PARTITION p20220611 VALUES LESS THAN ("20220612"), +PARTITION p20220612 VALUES LESS THAN ("20220613"), +PARTITION p20220613 VALUES LESS THAN ("20220614"), +PARTITION p20220614 VALUES LESS THAN ("20220615"), +PARTITION p20220615 VALUES LESS THAN ("20220616"), +PARTITION p20220616 VALUES LESS THAN ("20220617"), +PARTITION p20220617 VALUES LESS THAN ("20220618"), +PARTITION p20220618 VALUES LESS THAN ("20220619"), +PARTITION p20220619 VALUES LESS THAN ("20220620"), +PARTITION p20220620 VALUES LESS THAN ("20220621"), +PARTITION p20220621 VALUES LESS THAN ("20220622"), +PARTITION p20220622 VALUES LESS THAN ("20220623"), +PARTITION p20220623 VALUES LESS THAN ("20220624"), +PARTITION p20220624 VALUES LESS THAN ("20220625") + );`) + tk.MustExec("insert into t100(col1,money,logtime) values (100,10,'2022-06-09 00:00:00');") + tk.MustExec("insert into t100(col1,money,logtime) values (100,10,'2022-06-10 00:00:00');") + tk.MustQuery("SELECT /*+STREAM_AGG()*/ col1,sum(money) FROM t100 WHERE logtime>='2022-06-09 00:00:00' AND col1=100 ;").Check(testkit.Rows("100 20")) + tk.MustQuery("SELECT /*+HASH_AGG()*/ col1,sum(money) FROM t100 WHERE logtime>='2022-06-09 00:00:00' AND col1=100 ;").Check(testkit.Rows("100 20")) +} + +// https://github.com/pingcap/tidb/issues/27751 +func TestIssue27751(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec("use test") + tk.MustExec("drop table if exists t") + tk.MustExec("create table test.t(nname char(20));") + tk.MustExec("insert into test.t values ('2'),(null),('11'),('2'),(null),('2'),(null),('11'),('33');") + tk.MustExec("set @@group_concat_max_len=0;") + tk.MustQuery("select group_concat(nname order by 1 separator '#' ) from t;").Check(testkit.Rows("11#1")) + tk.MustQuery("select group_concat(nname order by 1 desc separator '#' ) from t;").Check(testkit.Rows("33#2")) +} + +func TestIssue26885(t *testing.T) { + store, clean := testkit.CreateMockStore(t) + defer clean() + tk := testkit.NewTestKit(t, store) + tk.MustExec(`use test`) + tk.MustExec(`SET sql_mode = 'NO_ENGINE_SUBSTITUTION';`) + tk.MustExec(`DROP TABLE IF EXISTS t1;`) + + tk.MustExec("CREATE TABLE t1 (c1 ENUM('a', '', 'b'));") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('b');") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('');") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('a');") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('');") + tk.MustExec("INSERT INTO t1 (c1) VALUES (0);") + tk.MustQuery("select * from t1").Check(testkit.Rows("b", "", "a", "", "")) + tk.MustQuery("select c1 + 0 from t1").Check(testkit.Rows("3", "2", "1", "2", "0")) + tk.MustQuery("SELECT c1 + 0, COUNT(c1) FROM t1 GROUP BY c1 order by c1;").Check(testkit.Rows("0 1", "1 1", "2 2", "3 1")) + + tk.MustExec("alter table t1 add index idx(c1); ") + tk.MustQuery("select c1 + 0 from t1").Check(testkit.Rows("3", "2", "1", "2", "0")) + tk.MustQuery("SELECT c1 + 0, COUNT(c1) FROM t1 GROUP BY c1 order by c1;").Check(testkit.Rows("0 1", "1 1", "2 2", "3 1")) + + tk.MustExec(`DROP TABLE IF EXISTS t1;`) + tk.MustExec("CREATE TABLE t1 (c1 ENUM('a', 'b', 'c'));") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('b');") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('a');") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('b');") + tk.MustExec("INSERT INTO t1 (c1) VALUES ('c');") + tk.MustExec("INSERT INTO t1 (c1) VALUES (0);") + tk.MustQuery("select * from t1").Check(testkit.Rows("b", "a", "b", "c", "")) + tk.MustQuery("SELECT c1 + 0, COUNT(c1) FROM t1 GROUP BY c1 order by c1;").Check(testkit.Rows("0 1", "1 1", "2 2", "3 1")) +} +>>>>>>> 065563a8e... executor: fix aggregating enum zero value gets different results from mysql (#36208)