From 3da045d7961c6477b24ef282afe9a9c811339b91 Mon Sep 17 00:00:00 2001 From: Chao Wang Date: Wed, 19 Jun 2024 13:52:08 +0800 Subject: [PATCH 1/2] *: use `StaticExprContext` instead of mock context to build expression --- pkg/ddl/partition.go | 6 +++--- pkg/table/tables/BUILD.bazel | 2 +- pkg/table/tables/partition.go | 6 +++--- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/pkg/ddl/partition.go b/pkg/ddl/partition.go index 87a1f7b0b4f64..c095f9bdd7b5b 100644 --- a/pkg/ddl/partition.go +++ b/pkg/ddl/partition.go @@ -33,6 +33,7 @@ import ( "github.com/pingcap/tidb/pkg/ddl/placement" "github.com/pingcap/tidb/pkg/domain/infosync" "github.com/pingcap/tidb/pkg/expression" + "github.com/pingcap/tidb/pkg/expression/contextstatic" "github.com/pingcap/tidb/pkg/infoschema" "github.com/pingcap/tidb/pkg/kv" "github.com/pingcap/tidb/pkg/meta" @@ -59,7 +60,6 @@ import ( "github.com/pingcap/tidb/pkg/util/dbterror" "github.com/pingcap/tidb/pkg/util/hack" "github.com/pingcap/tidb/pkg/util/mathutil" - "github.com/pingcap/tidb/pkg/util/mock" decoder "github.com/pingcap/tidb/pkg/util/rowDecoder" "github.com/pingcap/tidb/pkg/util/slice" "github.com/pingcap/tidb/pkg/util/stringutil" @@ -4259,9 +4259,9 @@ func (cns columnNameSlice) At(i int) string { } func isPartExprUnsigned(ectx expression.EvalContext, tbInfo *model.TableInfo) bool { - // We should not rely on any configuration, system or session variables, so use a mock ctx! + // We should not rely on any configuration, system or session variables, so use a default context. // Same as in tables.newPartitionExpr - ctx := mock.NewContext() + ctx := contextstatic.NewStaticExprContext() expr, err := expression.ParseSimpleExpr(ctx, tbInfo.Partition.Expr, expression.WithTableInfo("", tbInfo)) if err != nil { logutil.DDLLogger().Error("isPartExpr failed parsing expression!", zap.Error(err)) diff --git a/pkg/table/tables/BUILD.bazel b/pkg/table/tables/BUILD.bazel index 9250a29fa3947..8a54ff8bfc041 100644 --- a/pkg/table/tables/BUILD.bazel +++ b/pkg/table/tables/BUILD.bazel @@ -18,6 +18,7 @@ go_library( "//pkg/errno", "//pkg/expression", "//pkg/expression/context", + "//pkg/expression/contextstatic", "//pkg/kv", "//pkg/meta", "//pkg/meta/autoid", @@ -43,7 +44,6 @@ go_library( "//pkg/util/generatedexpr", "//pkg/util/hack", "//pkg/util/logutil", - "//pkg/util/mock", "//pkg/util/ranger", "//pkg/util/rowcodec", "//pkg/util/sqlexec", diff --git a/pkg/table/tables/partition.go b/pkg/table/tables/partition.go index 0525258813866..1c6bf4b4af3ca 100644 --- a/pkg/table/tables/partition.go +++ b/pkg/table/tables/partition.go @@ -29,6 +29,7 @@ import ( "github.com/pingcap/errors" "github.com/pingcap/tidb/pkg/errctx" "github.com/pingcap/tidb/pkg/expression" + "github.com/pingcap/tidb/pkg/expression/contextstatic" "github.com/pingcap/tidb/pkg/kv" "github.com/pingcap/tidb/pkg/parser" "github.com/pingcap/tidb/pkg/parser/ast" @@ -44,7 +45,6 @@ import ( "github.com/pingcap/tidb/pkg/util/dbterror" "github.com/pingcap/tidb/pkg/util/hack" "github.com/pingcap/tidb/pkg/util/logutil" - "github.com/pingcap/tidb/pkg/util/mock" "github.com/pingcap/tidb/pkg/util/ranger" "github.com/pingcap/tidb/pkg/util/stringutil" "go.uber.org/zap" @@ -240,8 +240,8 @@ func initPartition(t *partitionedTable, def model.PartitionDefinition) (*partiti func newPartitionExpr(tblInfo *model.TableInfo, tp model.PartitionType, expr string, partCols []model.CIStr, defs []model.PartitionDefinition) (*PartitionExpr, error) { // a partitioned table cannot rely on session context/sql modes, so use a default one! - ctx := mock.NewContext() - dbName := model.NewCIStr(ctx.GetSessionVars().CurrentDB) + ctx := contextstatic.NewStaticExprContext() + dbName := model.NewCIStr(ctx.GetEvalCtx().CurrentDB()) columns, names, err := expression.ColumnInfos2ColumnsAndNames(ctx, dbName, tblInfo.Name, tblInfo.Cols(), tblInfo) if err != nil { return nil, err From b7c9243be131cc53863419d24830d94e1f0db8bb Mon Sep 17 00:00:00 2001 From: Chao Wang Date: Thu, 27 Jun 2024 13:38:58 +0800 Subject: [PATCH 2/2] fix some bug --- pkg/ddl/partition.go | 5 +--- pkg/table/tables/partition.go | 24 +++++++++++++++++-- .../integrationtest/r/table/partition.result | 17 +++++++++++++ tests/integrationtest/t/table/partition.test | 14 +++++++++++ 4 files changed, 54 insertions(+), 6 deletions(-) diff --git a/pkg/ddl/partition.go b/pkg/ddl/partition.go index c095f9bdd7b5b..55ef0d59b624c 100644 --- a/pkg/ddl/partition.go +++ b/pkg/ddl/partition.go @@ -33,7 +33,6 @@ import ( "github.com/pingcap/tidb/pkg/ddl/placement" "github.com/pingcap/tidb/pkg/domain/infosync" "github.com/pingcap/tidb/pkg/expression" - "github.com/pingcap/tidb/pkg/expression/contextstatic" "github.com/pingcap/tidb/pkg/infoschema" "github.com/pingcap/tidb/pkg/kv" "github.com/pingcap/tidb/pkg/meta" @@ -4259,9 +4258,7 @@ func (cns columnNameSlice) At(i int) string { } func isPartExprUnsigned(ectx expression.EvalContext, tbInfo *model.TableInfo) bool { - // We should not rely on any configuration, system or session variables, so use a default context. - // Same as in tables.newPartitionExpr - ctx := contextstatic.NewStaticExprContext() + ctx := tables.NewPartitionExprBuildCtx() expr, err := expression.ParseSimpleExpr(ctx, tbInfo.Partition.Expr, expression.WithTableInfo("", tbInfo)) if err != nil { logutil.DDLLogger().Error("isPartExpr failed parsing expression!", zap.Error(err)) diff --git a/pkg/table/tables/partition.go b/pkg/table/tables/partition.go index 1c6bf4b4af3ca..918407c0061d9 100644 --- a/pkg/table/tables/partition.go +++ b/pkg/table/tables/partition.go @@ -238,9 +238,29 @@ func initPartition(t *partitionedTable, def model.PartitionDefinition) (*partiti return &newPart, nil } +// NewPartitionExprBuildCtx returns a context to build partition expression. +func NewPartitionExprBuildCtx() expression.BuildContext { + return contextstatic.NewStaticExprContext( + contextstatic.WithEvalCtx(contextstatic.NewStaticEvalContext( + // Set a non-strict SQL mode and allow all date values if possible to make sure constant fold can work to + // estimate some undetermined result when locating a row to a partition. + // See issue: https://github.com/pingcap/tidb/issues/54271 for details. + contextstatic.WithSQLMode(mysql.ModeAllowInvalidDates), + contextstatic.WithTypeFlags(types.StrictFlags. + WithIgnoreTruncateErr(true). + WithIgnoreZeroDateErr(true). + WithIgnoreZeroInDate(true). + WithIgnoreInvalidDateErr(true), + ), + contextstatic.WithErrLevelMap(errctx.LevelMap{ + errctx.ErrGroupTruncate: errctx.LevelIgnore, + }), + )), + ) +} + func newPartitionExpr(tblInfo *model.TableInfo, tp model.PartitionType, expr string, partCols []model.CIStr, defs []model.PartitionDefinition) (*PartitionExpr, error) { - // a partitioned table cannot rely on session context/sql modes, so use a default one! - ctx := contextstatic.NewStaticExprContext() + ctx := NewPartitionExprBuildCtx() dbName := model.NewCIStr(ctx.GetEvalCtx().CurrentDB()) columns, names, err := expression.ColumnInfos2ColumnsAndNames(ctx, dbName, tblInfo.Name, tblInfo.Cols(), tblInfo) if err != nil { diff --git a/tests/integrationtest/r/table/partition.result b/tests/integrationtest/r/table/partition.result index dd0e89f64c8cc..35e13c1a5a2fe 100644 --- a/tests/integrationtest/r/table/partition.result +++ b/tests/integrationtest/r/table/partition.result @@ -569,3 +569,20 @@ a -1 0 1 +set @@sql_mode='allow_invalid_dates'; +create table t_54271(a datetime primary key) partition by range columns(a) ( +partition p0 values less than ('2020-02-31 00:00:00'), +partition p1 values less than (MAXVALUE) +); +insert into t_54271 values('2020-03-01 00:00:00'); +set @@sql_mode=''; +insert into t_54271 values('2020-03-01 00:00:00'); +Error 1062 (23000): Duplicate entry '2020-03-01 00:00:00' for key 't_54271.PRIMARY' +select * from t_54271; +a +2020-03-01 00:00:00 +select * from t_54271 partition (p0); +a +select * from t_54271 partition (p1); +a +2020-03-01 00:00:00 diff --git a/tests/integrationtest/t/table/partition.test b/tests/integrationtest/t/table/partition.test index a0117b376c973..2856d0d303318 100644 --- a/tests/integrationtest/t/table/partition.test +++ b/tests/integrationtest/t/table/partition.test @@ -430,3 +430,17 @@ alter table t partition by range(a) (partition p0 values less than (0), partitio alter table t remove partitioning; select * from t; +# Issue #54271 +set @@sql_mode='allow_invalid_dates'; +create table t_54271(a datetime primary key) partition by range columns(a) ( + partition p0 values less than ('2020-02-31 00:00:00'), + partition p1 values less than (MAXVALUE) +); +insert into t_54271 values('2020-03-01 00:00:00'); +set @@sql_mode=''; +--error 1062 +insert into t_54271 values('2020-03-01 00:00:00'); +select * from t_54271; +select * from t_54271 partition (p0); +select * from t_54271 partition (p1); +