From ba443b34bc912ce682660207d472da33eb448ea8 Mon Sep 17 00:00:00 2001 From: Lingyu Song Date: Tue, 1 Sep 2020 14:49:02 +0800 Subject: [PATCH 1/2] cherry pick #18818 to release-3.0 Signed-off-by: ti-srebot --- planner/core/common_plans.go | 23 ++++ table/tables/partition.go | 219 ++++++++++++++++++++++++++++++++- table/tables/partition_test.go | 84 ++++++++++++- 3 files changed, 320 insertions(+), 6 deletions(-) diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index 715148ec35122..37fb5652918e2 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -301,6 +301,18 @@ func (e *Execute) rebuildRange(p Plan) error { if err != nil { return err } +<<<<<<< HEAD +======= + x.Handle = kv.IntHandle(iv) + if x.PartitionInfo != nil { + if x.TblInfo.Partition.Type != model.PartitionTypeHash { + return errors.New("range partition table can not use plan cache") + } + num := x.TblInfo.Partition.Num + pos := math.Abs(iv) % int64(num) + x.PartitionInfo = &x.TblInfo.Partition.Definitions[pos] + } +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) return nil } for i, param := range x.IndexValueParams { @@ -308,6 +320,17 @@ func (e *Execute) rebuildRange(p Plan) error { x.IndexValues[i] = param.Datum } } +<<<<<<< HEAD +======= + if x.PartitionInfo != nil { + if x.TblInfo.Partition.Type != model.PartitionTypeHash { + return errors.New("range partition table can not use plan cache") + } + val := x.IndexValues[x.partitionColumnPos].GetInt64() + partitionID := val % int64(x.TblInfo.Partition.Num) + x.PartitionInfo = &x.TblInfo.Partition.Definitions[partitionID] + } +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) return nil case PhysicalPlan: for _, child := range x.Children() { diff --git a/table/tables/partition.go b/table/tables/partition.go index 98baf9c7a856d..47fe6f5c7b709 100644 --- a/table/tables/partition.go +++ b/table/tables/partition.go @@ -21,9 +21,11 @@ import ( "sort" "strconv" "strings" + "sync" "github.com/pingcap/errors" "github.com/pingcap/parser/model" + "github.com/pingcap/parser/mysql" "github.com/pingcap/tidb/expression" "github.com/pingcap/tidb/kv" "github.com/pingcap/tidb/sessionctx" @@ -61,9 +63,17 @@ func (p *partition) GetPhysicalID() int64 { // partitionedTable implements the table.PartitionedTable interface. // partitionedTable is a table, it contains many Partitions. type partitionedTable struct { +<<<<<<< HEAD Table partitionExpr *PartitionExpr partitions map[int64]*partition +======= + TableCommon + partitionExpr *PartitionExpr + partitions map[int64]*partition + evalBufferTypes []*types.FieldType + evalBufferPool sync.Pool +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) } func newPartitionedTable(tbl *Table, tblInfo *model.TableInfo) (table.Table, error) { @@ -73,8 +83,18 @@ func newPartitionedTable(tbl *Table, tblInfo *model.TableInfo) (table.Table, err return nil, errors.Trace(err) } ret.partitionExpr = partitionExpr +<<<<<<< HEAD if err := initTableIndices(&ret.tableCommon); err != nil { +======= + initEvalBufferType(ret) + ret.evalBufferPool = sync.Pool{ + New: func() interface{} { + return initEvalBuffer(ret) + }, + } + if err := initTableIndices(&ret.TableCommon); err != nil { +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) return nil, errors.Trace(err) } partitions := make(map[int64]*partition) @@ -127,6 +147,60 @@ type PartitionExpr struct { UpperBounds []expression.Expression // Expr is the hash partition expression. Expr expression.Expression +<<<<<<< HEAD +======= + // Used in the range pruning process. + *ForRangePruning + // Used in the range column pruning process. + *ForRangeColumnsPruning +} + +func initEvalBufferType(t *partitionedTable) { + hasExtraHandle := false + numCols := len(t.Cols()) + if !t.Meta().PKIsHandle { + hasExtraHandle = true + numCols++ + } + t.evalBufferTypes = make([]*types.FieldType, numCols) + for i, col := range t.Cols() { + t.evalBufferTypes[i] = &col.FieldType + } + + if hasExtraHandle { + t.evalBufferTypes[len(t.evalBufferTypes)-1] = types.NewFieldType(mysql.TypeLonglong) + } +} + +func initEvalBuffer(t *partitionedTable) *chunk.MutRow { + evalBuffer := chunk.MutRowFromTypes(t.evalBufferTypes) + return &evalBuffer +} + +// ForRangeColumnsPruning is used for range partition pruning. +type ForRangeColumnsPruning struct { + LessThan []expression.Expression + MaxValue bool +} + +func dataForRangeColumnsPruning(ctx sessionctx.Context, pi *model.PartitionInfo, schema *expression.Schema, names []*types.FieldName, p *parser.Parser) (*ForRangeColumnsPruning, error) { + var res ForRangeColumnsPruning + res.LessThan = make([]expression.Expression, len(pi.Definitions)) + for i := 0; i < len(pi.Definitions); i++ { + if strings.EqualFold(pi.Definitions[i].LessThan[0], "MAXVALUE") { + // Use a bool flag instead of math.MaxInt64 to avoid the corner cases. + res.MaxValue = true + } else { + tmp, err := parseSimpleExprWithNames(p, ctx, pi.Definitions[i].LessThan[0], schema, names) + if err != nil { + return nil, err + } + res.LessThan[i] = tmp + } + } + return &res, nil +} +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) // The new range partition pruning *ForRangePruning @@ -188,6 +262,7 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, partitionPruneExprs := make([]expression.Expression, 0, len(pi.Definitions)) locateExprs := make([]expression.Expression, 0, len(pi.Definitions)) var buf bytes.Buffer + p := parser.New() schema := expression.NewSchema(columns...) partStr := rangePartitionString(pi) for i := 0; i < len(pi.Definitions); i++ { @@ -207,6 +282,7 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, } locateExprs = append(locateExprs, exprs[0]) +<<<<<<< HEAD if i > 0 { fmt.Fprintf(&buf, " and ((%s) >= (%s))", partStr, pi.Definitions[i-1].LessThan[0]) } else { @@ -225,11 +301,21 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, } exprs, err = expression.ParseSimpleExprsWithSchema(ctx, buf.String(), schema) +======= + switch len(pi.Columns) { + case 0: + exprs, err := parseSimpleExprWithNames(p, ctx, pi.Expr, schema, names) + if err != nil { + return nil, err + } + tmp, err := dataForRangePruning(ctx, pi) +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) if err != nil { // If it got an error here, ddl may hang forever, so this error log is important. logutil.Logger(context.Background()).Error("wrong table partition expression", zap.String("expression", buf.String()), zap.Error(err)) return nil, errors.Trace(err) } +<<<<<<< HEAD // Get a hash code in advance to prevent data race afterwards. exprs[0].HashCode(ctx.GetSessionVars().StmtCtx) partitionPruneExprs = append(partitionPruneExprs, exprs[0]) @@ -240,6 +326,12 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, if len(pi.Columns) == 0 { rangePruning = &ForRangePruning{} err := makeLessThanData(pi, rangePruning) +======= + ret.Expr = exprs + ret.ForRangePruning = tmp + case 1: + tmp, err := dataForRangeColumnsPruning(ctx, pi, schema, names, p) +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) if err != nil { return nil, errors.Trace(err) } @@ -313,7 +405,11 @@ func (t *partitionedTable) locatePartition(ctx sessionctx.Context, pi *model.Par var idx int switch t.meta.Partition.Type { case model.PartitionTypeRange: - idx, err = t.locateRangePartition(ctx, pi, r) + if len(pi.Columns) == 0 { + idx, err = t.locateRangePartition(ctx, pi, r) + } else { + idx, err = t.locateRangeColumnPartition(ctx, pi, r) + } case model.PartitionTypeHash: idx, err = t.locateHashPartition(ctx, pi, r) } @@ -323,13 +419,15 @@ func (t *partitionedTable) locatePartition(ctx sessionctx.Context, pi *model.Par return pi.Definitions[idx].ID, nil } -func (t *partitionedTable) locateRangePartition(ctx sessionctx.Context, pi *model.PartitionInfo, r []types.Datum) (int, error) { +func (t *partitionedTable) locateRangeColumnPartition(ctx sessionctx.Context, pi *model.PartitionInfo, r []types.Datum) (int, error) { var err error var isNull bool partitionExprs := t.partitionExpr.UpperBounds + evalBuffer := t.evalBufferPool.Get().(*chunk.MutRow) + defer t.evalBufferPool.Put(evalBuffer) idx := sort.Search(len(partitionExprs), func(i int) bool { - var ret int64 - ret, isNull, err = partitionExprs[i].EvalInt(ctx, chunk.MutRowFromDatums(r).ToRow()) + evalBuffer.SetDatums(r...) + ret, isNull, err := partitionExprs[i].EvalInt(ctx, evalBuffer.ToRow()) if err != nil { return true // Break the search. } @@ -366,9 +464,74 @@ func (t *partitionedTable) locateRangePartition(ctx sessionctx.Context, pi *mode return idx, nil } +func (t *partitionedTable) locateRangePartition(ctx sessionctx.Context, pi *model.PartitionInfo, r []types.Datum) (int, error) { + var ( + ret int64 + val int64 + isNull bool + err error + ) + if col, ok := t.partitionExpr.Expr.(*expression.Column); ok { + if r[col.Index].IsNull() { + isNull = true + } + ret = r[col.Index].GetInt64() + } else { + evalBuffer := t.evalBufferPool.Get().(*chunk.MutRow) + defer t.evalBufferPool.Put(evalBuffer) + evalBuffer.SetDatums(r...) + val, isNull, err = t.partitionExpr.Expr.EvalInt(ctx, evalBuffer.ToRow()) + if err != nil { + return 0, err + } + ret = val + } + unsigned := mysql.HasUnsignedFlag(t.partitionExpr.Expr.GetType().Flag) + ranges := t.partitionExpr.ForRangePruning + length := len(ranges.LessThan) + pos := sort.Search(length, func(i int) bool { + if isNull { + return true + } + return ranges.compare(i, ret, unsigned) > 0 + }) + if isNull { + pos = 0 + } + if pos < 0 || pos >= length { + // The data does not belong to any of the partition returns `table has no partition for value %s`. + var valueMsg string + if pi.Expr != "" { + e, err := expression.ParseSimpleExprWithTableInfo(ctx, pi.Expr, t.meta) + if err == nil { + val, _, err := e.EvalInt(ctx, chunk.MutRowFromDatums(r).ToRow()) + if err == nil { + valueMsg = fmt.Sprintf("%d", val) + } + } + } else { + // When the table is partitioned by range columns. + valueMsg = "from column_list" + } + return 0, table.ErrNoPartitionForGivenValue.GenWithStackByArgs(valueMsg) + } + return pos, nil +} + // TODO: supports linear hashing func (t *partitionedTable) locateHashPartition(ctx sessionctx.Context, pi *model.PartitionInfo, r []types.Datum) (int, error) { - ret, isNull, err := t.partitionExpr.Expr.EvalInt(ctx, chunk.MutRowFromDatums(r).ToRow()) + if col, ok := t.partitionExpr.Expr.(*expression.Column); ok { + ret := r[col.Index].GetInt64() + ret = ret % int64(t.meta.Partition.Num) + if ret < 0 { + ret = -ret + } + return int(ret), nil + } + evalBuffer := t.evalBufferPool.Get().(*chunk.MutRow) + defer t.evalBufferPool.Put(evalBuffer) + evalBuffer.SetDatums(r...) + ret, isNull, err := t.partitionExpr.Expr.EvalInt(ctx, evalBuffer.ToRow()) if err != nil { return 0, err } @@ -475,3 +638,49 @@ func FindPartitionByName(meta *model.TableInfo, parName string) (int64, error) { } return -1, errors.Trace(table.ErrUnknownPartition.GenWithStackByArgs(parName, meta.Name.O)) } +<<<<<<< HEAD +======= + +func parseExpr(p *parser.Parser, exprStr string) (ast.ExprNode, error) { + exprStr = "select " + exprStr + stmts, _, err := p.Parse(exprStr, "", "") + if err != nil { + return nil, util.SyntaxWarn(err) + } + fields := stmts[0].(*ast.SelectStmt).Fields.Fields + return fields[0].Expr, nil +} + +func rewritePartitionExpr(ctx sessionctx.Context, field ast.ExprNode, schema *expression.Schema, names types.NameSlice) (expression.Expression, error) { + expr, err := expression.RewriteSimpleExprWithNames(ctx, field, schema, names) + return expr, err +} + +func compareUnsigned(v1, v2 int64) int { + switch { + case uint64(v1) > uint64(v2): + return 1 + case uint64(v1) == uint64(v2): + return 0 + } + return -1 +} + +func (lt *ForRangePruning) compare(ith int, v int64, unsigned bool) int { + if ith == len(lt.LessThan)-1 { + if lt.MaxValue { + return 1 + } + } + if unsigned { + return compareUnsigned(lt.LessThan[ith], v) + } + switch { + case lt.LessThan[ith] > v: + return 1 + case lt.LessThan[ith] == v: + return 0 + } + return -1 +} +>>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) diff --git a/table/tables/partition_test.go b/table/tables/partition_test.go index 4c3314ae35927..22a64ac864f12 100644 --- a/table/tables/partition_test.go +++ b/table/tables/partition_test.go @@ -294,7 +294,7 @@ func (ts *testSuite) TestGeneratePartitionExpr(c *C) { } } -func (ts *testSuite) TestLocateRangePartitionErr(c *C) { +func (ts *testSuite) TestLocateRangeColumnPartitionErr(c *C) { tk := testkit.NewTestKitWithInit(c, ts.store) tk.MustExec("use test") tk.MustExec(`CREATE TABLE t_month_data_monitor ( @@ -310,6 +310,88 @@ func (ts *testSuite) TestLocateRangePartitionErr(c *C) { c.Assert(table.ErrNoPartitionForGivenValue.Equal(err), IsTrue) } +func (ts *testSuite) TestLocateRangePartitionErr(c *C) { + tk := testkit.NewTestKitWithInit(c, ts.store) + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE t_range_locate ( + id int(20) NOT NULL AUTO_INCREMENT, + data_date date NOT NULL, + PRIMARY KEY (id, data_date) + ) PARTITION BY RANGE(id) ( + PARTITION p0 VALUES LESS THAN (1024), + PARTITION p1 VALUES LESS THAN (4096) + )`) + + _, err := tk.Exec("INSERT INTO t_range_locate VALUES (5000, '2019-04-04')") + c.Assert(table.ErrNoPartitionForGivenValue.Equal(err), IsTrue) +} + +func (ts *testSuite) TestLocatePartitionWithExtraHandle(c *C) { + tk := testkit.NewTestKitWithInit(c, ts.store) + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE t_extra ( + id int(20) NOT NULL AUTO_INCREMENT, + x int(10) not null, + PRIMARY KEY (id, x) + ) PARTITION BY RANGE(id) ( + PARTITION p0 VALUES LESS THAN (1024), + PARTITION p1 VALUES LESS THAN (4096) + )`) + tk.MustExec("INSERT INTO t_extra VALUES (1000, 1000), (2000, 2000)") + tk.MustExec("set autocommit=0;") + tk.MustQuery("select * from t_extra where id = 1000 for update").Check(testkit.Rows("1000 1000")) + tk.MustExec("commit") +} + +func (ts *testSuite) TestMultiTableUpdate(c *C) { + tk := testkit.NewTestKitWithInit(c, ts.store) + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE t_a ( + id int(20), + data_date date + ) partition by hash(id) partitions 10`) + tk.MustExec(`CREATE TABLE t_b ( + id int(20), + data_date date + ) PARTITION BY RANGE(id) ( + PARTITION p0 VALUES LESS THAN (2), + PARTITION p1 VALUES LESS THAN (4), + PARTITION p2 VALUES LESS THAN (6) + )`) + tk.MustExec("INSERT INTO t_a VALUES (1, '2020-08-25'), (2, '2020-08-25'), (3, '2020-08-25'), (4, '2020-08-25'), (5, '2020-08-25')") + tk.MustExec("INSERT INTO t_b VALUES (1, '2020-08-25'), (2, '2020-08-25'), (3, '2020-08-25'), (4, '2020-08-25'), (5, '2020-08-25')") + tk.MustExec("update t_a, t_b set t_a.data_date = '2020-08-24', t_a.data_date = '2020-08-23', t_a.id = t_a.id + t_b.id where t_a.id = t_b.id") + tk.MustQuery("select id from t_a order by id").Check(testkit.Rows("2", "4", "6", "8", "10")) +} + +func (ts *testSuite) TestLocatePartitionSingleColumn(c *C) { + tk := testkit.NewTestKitWithInit(c, ts.store) + tk.MustExec("use test") + tk.MustExec(`CREATE TABLE t_hash_locate ( + id int(20), + data_date date + ) partition by hash(id) partitions 10`) + + tk.MustExec(`CREATE TABLE t_range ( + id int(10) NOT NULL, + data_date date, + PRIMARY KEY (id) + ) PARTITION BY RANGE(id) ( + PARTITION p0 VALUES LESS THAN (1), + PARTITION p1 VALUES LESS THAN (2), + PARTITION p2 VALUES LESS THAN (4) + )`) + + tk.MustExec("INSERT INTO t_hash_locate VALUES (), (), (), ()") + tk.MustQuery("SELECT count(*) FROM t_hash_locate PARTITION (p0)").Check(testkit.Rows("4")) + tk.MustExec("INSERT INTO t_range VALUES (-1, NULL), (1, NULL), (2, NULL), (3, NULL)") + tk.MustQuery("SELECT count(*) FROM t_range PARTITION (p0)").Check(testkit.Rows("1")) + tk.MustQuery("SELECT count(*) FROM t_range PARTITION (p1)").Check(testkit.Rows("1")) + tk.MustQuery("SELECT count(*) FROM t_range PARTITION (p2)").Check(testkit.Rows("2")) + _, err := tk.Exec("INSERT INTO t_range VALUES (4, NULL)") + c.Assert(table.ErrNoPartitionForGivenValue.Equal(err), IsTrue) +} + func (ts *testSuite) TestTimeZoneChange(c *C) { tk := testkit.NewTestKitWithInit(c, ts.store) tk.MustExec("use test") From 3630c3756f57cd2fe1136fef85e4051cc0fc384d Mon Sep 17 00:00:00 2001 From: imtbkcat Date: Wed, 2 Sep 2020 15:33:19 +0800 Subject: [PATCH 2/2] fix conflict --- planner/core/common_plans.go | 23 -------- table/tables/partition.go | 103 +++++------------------------------ 2 files changed, 15 insertions(+), 111 deletions(-) diff --git a/planner/core/common_plans.go b/planner/core/common_plans.go index 37fb5652918e2..715148ec35122 100644 --- a/planner/core/common_plans.go +++ b/planner/core/common_plans.go @@ -301,18 +301,6 @@ func (e *Execute) rebuildRange(p Plan) error { if err != nil { return err } -<<<<<<< HEAD -======= - x.Handle = kv.IntHandle(iv) - if x.PartitionInfo != nil { - if x.TblInfo.Partition.Type != model.PartitionTypeHash { - return errors.New("range partition table can not use plan cache") - } - num := x.TblInfo.Partition.Num - pos := math.Abs(iv) % int64(num) - x.PartitionInfo = &x.TblInfo.Partition.Definitions[pos] - } ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) return nil } for i, param := range x.IndexValueParams { @@ -320,17 +308,6 @@ func (e *Execute) rebuildRange(p Plan) error { x.IndexValues[i] = param.Datum } } -<<<<<<< HEAD -======= - if x.PartitionInfo != nil { - if x.TblInfo.Partition.Type != model.PartitionTypeHash { - return errors.New("range partition table can not use plan cache") - } - val := x.IndexValues[x.partitionColumnPos].GetInt64() - partitionID := val % int64(x.TblInfo.Partition.Num) - x.PartitionInfo = &x.TblInfo.Partition.Definitions[partitionID] - } ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) return nil case PhysicalPlan: for _, child := range x.Children() { diff --git a/table/tables/partition.go b/table/tables/partition.go index 47fe6f5c7b709..e7bd03f040c01 100644 --- a/table/tables/partition.go +++ b/table/tables/partition.go @@ -63,17 +63,11 @@ func (p *partition) GetPhysicalID() int64 { // partitionedTable implements the table.PartitionedTable interface. // partitionedTable is a table, it contains many Partitions. type partitionedTable struct { -<<<<<<< HEAD Table - partitionExpr *PartitionExpr - partitions map[int64]*partition -======= - TableCommon partitionExpr *PartitionExpr partitions map[int64]*partition evalBufferTypes []*types.FieldType evalBufferPool sync.Pool ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) } func newPartitionedTable(tbl *Table, tblInfo *model.TableInfo) (table.Table, error) { @@ -83,18 +77,8 @@ func newPartitionedTable(tbl *Table, tblInfo *model.TableInfo) (table.Table, err return nil, errors.Trace(err) } ret.partitionExpr = partitionExpr -<<<<<<< HEAD if err := initTableIndices(&ret.tableCommon); err != nil { -======= - initEvalBufferType(ret) - ret.evalBufferPool = sync.Pool{ - New: func() interface{} { - return initEvalBuffer(ret) - }, - } - if err := initTableIndices(&ret.TableCommon); err != nil { ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) return nil, errors.Trace(err) } partitions := make(map[int64]*partition) @@ -108,6 +92,12 @@ func newPartitionedTable(tbl *Table, tblInfo *model.TableInfo) (table.Table, err partitions[p.ID] = &t } ret.partitions = partitions + initEvalBufferType(ret) + ret.evalBufferPool = sync.Pool{ + New: func() interface{} { + return initEvalBuffer(ret) + }, + } return ret, nil } @@ -147,12 +137,8 @@ type PartitionExpr struct { UpperBounds []expression.Expression // Expr is the hash partition expression. Expr expression.Expression -<<<<<<< HEAD -======= - // Used in the range pruning process. + // The new range partition pruning *ForRangePruning - // Used in the range column pruning process. - *ForRangeColumnsPruning } func initEvalBufferType(t *partitionedTable) { @@ -177,35 +163,6 @@ func initEvalBuffer(t *partitionedTable) *chunk.MutRow { return &evalBuffer } -// ForRangeColumnsPruning is used for range partition pruning. -type ForRangeColumnsPruning struct { - LessThan []expression.Expression - MaxValue bool -} - -func dataForRangeColumnsPruning(ctx sessionctx.Context, pi *model.PartitionInfo, schema *expression.Schema, names []*types.FieldName, p *parser.Parser) (*ForRangeColumnsPruning, error) { - var res ForRangeColumnsPruning - res.LessThan = make([]expression.Expression, len(pi.Definitions)) - for i := 0; i < len(pi.Definitions); i++ { - if strings.EqualFold(pi.Definitions[i].LessThan[0], "MAXVALUE") { - // Use a bool flag instead of math.MaxInt64 to avoid the corner cases. - res.MaxValue = true - } else { - tmp, err := parseSimpleExprWithNames(p, ctx, pi.Definitions[i].LessThan[0], schema, names) - if err != nil { - return nil, err - } - res.LessThan[i] = tmp - } - } - return &res, nil -} ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) - - // The new range partition pruning - *ForRangePruning -} - // ForRangePruning is used for range partition pruning. type ForRangePruning struct { LessThan []int64 @@ -262,7 +219,6 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, partitionPruneExprs := make([]expression.Expression, 0, len(pi.Definitions)) locateExprs := make([]expression.Expression, 0, len(pi.Definitions)) var buf bytes.Buffer - p := parser.New() schema := expression.NewSchema(columns...) partStr := rangePartitionString(pi) for i := 0; i < len(pi.Definitions); i++ { @@ -281,8 +237,6 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, return nil, errors.Trace(err) } locateExprs = append(locateExprs, exprs[0]) - -<<<<<<< HEAD if i > 0 { fmt.Fprintf(&buf, " and ((%s) >= (%s))", partStr, pi.Definitions[i-1].LessThan[0]) } else { @@ -301,21 +255,11 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, } exprs, err = expression.ParseSimpleExprsWithSchema(ctx, buf.String(), schema) -======= - switch len(pi.Columns) { - case 0: - exprs, err := parseSimpleExprWithNames(p, ctx, pi.Expr, schema, names) - if err != nil { - return nil, err - } - tmp, err := dataForRangePruning(ctx, pi) ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) if err != nil { // If it got an error here, ddl may hang forever, so this error log is important. logutil.Logger(context.Background()).Error("wrong table partition expression", zap.String("expression", buf.String()), zap.Error(err)) return nil, errors.Trace(err) } -<<<<<<< HEAD // Get a hash code in advance to prevent data race afterwards. exprs[0].HashCode(ctx.GetSessionVars().StmtCtx) partitionPruneExprs = append(partitionPruneExprs, exprs[0]) @@ -323,18 +267,18 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, } var rangePruning *ForRangePruning + var partitionExpr expression.Expression if len(pi.Columns) == 0 { + exprs, err := expression.ParseSimpleExprsWithSchema(ctx, pi.Expr, schema) + if err != nil { + return nil, err + } rangePruning = &ForRangePruning{} - err := makeLessThanData(pi, rangePruning) -======= - ret.Expr = exprs - ret.ForRangePruning = tmp - case 1: - tmp, err := dataForRangeColumnsPruning(ctx, pi, schema, names, p) ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818) + err = makeLessThanData(pi, rangePruning) if err != nil { return nil, errors.Trace(err) } + partitionExpr = exprs[0] } return &PartitionExpr{ @@ -342,6 +286,7 @@ func generatePartitionExpr(ctx sessionctx.Context, pi *model.PartitionInfo, Ranges: partitionPruneExprs, UpperBounds: locateExprs, ForRangePruning: rangePruning, + Expr: partitionExpr, }, nil } @@ -638,23 +583,6 @@ func FindPartitionByName(meta *model.TableInfo, parName string) (int64, error) { } return -1, errors.Trace(table.ErrUnknownPartition.GenWithStackByArgs(parName, meta.Name.O)) } -<<<<<<< HEAD -======= - -func parseExpr(p *parser.Parser, exprStr string) (ast.ExprNode, error) { - exprStr = "select " + exprStr - stmts, _, err := p.Parse(exprStr, "", "") - if err != nil { - return nil, util.SyntaxWarn(err) - } - fields := stmts[0].(*ast.SelectStmt).Fields.Fields - return fields[0].Expr, nil -} - -func rewritePartitionExpr(ctx sessionctx.Context, field ast.ExprNode, schema *expression.Schema, names types.NameSlice) (expression.Expression, error) { - expr, err := expression.RewriteSimpleExprWithNames(ctx, field, schema, names) - return expr, err -} func compareUnsigned(v1, v2 int64) int { switch { @@ -683,4 +611,3 @@ func (lt *ForRangePruning) compare(ith int, v int64, unsigned bool) int { } return -1 } ->>>>>>> 349adf8... table: use evalBuffer to improve performance of locatePartition (#18818)