Skip to content

Commit

Permalink
planner, executor: support insert/replace into partition (#17280) (#1…
Browse files Browse the repository at this point in the history
  • Loading branch information
sre-bot authored May 21, 2020
1 parent 029f95a commit 70e94b4
Show file tree
Hide file tree
Showing 4 changed files with 117 additions and 6 deletions.
89 changes: 89 additions & 0 deletions executor/executor_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5534,6 +5534,95 @@ func (s *testSuite1) TestInsertValuesWithSubQuery(c *C) {
tk.MustQuery("select * from t2").Check(testkit.Rows("2 4 2", "3 5 5"))
}

func (s *testSuite1) TestInsertIntoGivenPartitionSet(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test;")
tk.MustExec("drop table if exists t1")
tk.MustExec(`create table t1(
a int(11) DEFAULT NULL,
b varchar(10) DEFAULT NULL,
UNIQUE KEY idx_a (a)) PARTITION BY RANGE (a)
(PARTITION p0 VALUES LESS THAN (10) ENGINE = InnoDB,
PARTITION p1 VALUES LESS THAN (20) ENGINE = InnoDB,
PARTITION p2 VALUES LESS THAN (30) ENGINE = InnoDB,
PARTITION p3 VALUES LESS THAN (40) ENGINE = InnoDB,
PARTITION p4 VALUES LESS THAN MAXVALUE ENGINE = InnoDB)`)
defer tk.MustExec("drop table if exists t1")

// insert into
tk.MustExec("insert into t1 partition(p0) values(1, 'a'), (2, 'b')")
tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b"))
tk.MustExec("insert into t1 partition(p0, p1) values(3, 'c'), (4, 'd')")
tk.MustQuery("select * from t1 partition(p1)").Check(testkit.Rows())

err := tk.ExecToErr("insert into t1 values(1, 'a')")
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'idx_a'")

err = tk.ExecToErr("insert into t1 partition(p0, p_non_exist) values(1, 'a')")
c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p_non_exist' in table 't1'")

err = tk.ExecToErr("insert into t1 partition(p0, p1) values(40, 'a')")
c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set")

// replace into
tk.MustExec("replace into t1 partition(p0) values(1, 'replace')")
tk.MustExec("replace into t1 partition(p0, p1) values(3, 'replace'), (4, 'replace')")

err = tk.ExecToErr("replace into t1 values(1, 'a')")
tk.MustQuery("select * from t1 partition (p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 replace", "4 replace"))

err = tk.ExecToErr("replace into t1 partition(p0, p_non_exist) values(1, 'a')")
c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p_non_exist' in table 't1'")

err = tk.ExecToErr("replace into t1 partition(p0, p1) values(40, 'a')")
c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set")

tk.MustExec("truncate table t1")

tk.MustExec("drop table if exists t")
tk.MustExec("create table t(a int, b char(10))")
defer tk.MustExec("drop table if exists t")

// insert into general table
err = tk.ExecToErr("insert into t partition(p0, p1) values(1, 'a')")
c.Assert(err.Error(), Equals, "[planner:1747]PARTITION () clause on non partitioned table")

// insert into from select
tk.MustExec("insert into t values(1, 'a'), (2, 'b')")
tk.MustExec("insert into t1 partition(p0) select * from t")
tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b"))

tk.MustExec("truncate table t")
tk.MustExec("insert into t values(3, 'c'), (4, 'd')")
tk.MustExec("insert into t1 partition(p0, p1) select * from t")
tk.MustQuery("select * from t1 partition(p1) order by a").Check(testkit.Rows())
tk.MustQuery("select * from t1 partition(p0) order by a").Check(testkit.Rows("1 a", "2 b", "3 c", "4 d"))

err = tk.ExecToErr("insert into t1 select 1, 'a'")
c.Assert(err.Error(), Equals, "[kv:1062]Duplicate entry '1' for key 'idx_a'")

err = tk.ExecToErr("insert into t1 partition(p0, p_non_exist) select 1, 'a'")
c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p_non_exist' in table 't1'")

err = tk.ExecToErr("insert into t1 partition(p0, p1) select 40, 'a'")
c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set")

// replace into from select
tk.MustExec("replace into t1 partition(p0) select 1, 'replace'")
tk.MustExec("truncate table t")
tk.MustExec("insert into t values(3, 'replace'), (4, 'replace')")
tk.MustExec("replace into t1 partition(p0, p1) select * from t")

err = tk.ExecToErr("replace into t1 values select 1, 'a'")
tk.MustQuery("select * from t1 partition (p0) order by a").Check(testkit.Rows("1 replace", "2 b", "3 replace", "4 replace"))

err = tk.ExecToErr("replace into t1 partition(p0, p_non_exist) select 1, 'a'")
c.Assert(err.Error(), Equals, "[table:1735]Unknown partition 'p_non_exist' in table 't1'")

err = tk.ExecToErr("replace into t1 partition(p0, p1) select 40, 'a'")
c.Assert(err.Error(), Equals, "[table:1748]Found a row not matching the given partition set")
}

func (s *testSuite1) TestUpdateGivenPartitionSet(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test;")
Expand Down
6 changes: 3 additions & 3 deletions go.mod
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,8 @@ require (
github.com/pingcap/fn v0.0.0-20191016082858-07623b84a47d
github.com/pingcap/goleveldb v0.0.0-20191226122134-f82aafb29989
github.com/pingcap/kvproto v0.0.0-20200428135407-0f5ffe459677
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd
github.com/pingcap/parser v0.0.0-20200427031542-879c7bd4f27d
github.com/pingcap/log v0.0.0-20200511115504-543df19646ad
github.com/pingcap/parser v0.0.0-20200521064712-8dc0fb6ce6f4
github.com/pingcap/pd/v4 v4.0.0-rc.1.0.20200422143320-428acd53eba2
github.com/pingcap/sysutil v0.0.0-20200408114249-ed3bd6f7fdb1
github.com/pingcap/tidb-tools v4.0.0-rc.1.0.20200421113014-507d2bb3a15e+incompatible
Expand All @@ -49,7 +49,7 @@ require (
go.etcd.io/etcd v0.5.0-alpha.5.0.20191023171146-3cf2f69b5738
go.uber.org/atomic v1.6.0
go.uber.org/automaxprocs v1.2.0
go.uber.org/zap v1.14.1
go.uber.org/zap v1.15.0
golang.org/x/net v0.0.0-20200324143707-d3edc9973b7e
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd
Expand Down
9 changes: 7 additions & 2 deletions go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -366,9 +366,12 @@ github.com/pingcap/kvproto v0.0.0-20200428135407-0f5ffe459677/go.mod h1:IOdRDPLy
github.com/pingcap/log v0.0.0-20191012051959-b742a5d432e9/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8=
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd h1:CV3VsP3Z02MVtdpTMfEgRJ4T9NGgGTxdHpJerent7rM=
github.com/pingcap/log v0.0.0-20200117041106-d28c14d3b1cd/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8=
github.com/pingcap/log v0.0.0-20200511115504-543df19646ad h1:SveG82rmu/GFxYanffxsSF503SiQV+2JLnWEiGiF+Tc=
github.com/pingcap/log v0.0.0-20200511115504-543df19646ad/go.mod h1:4rbK1p9ILyIfb6hU7OG2CiWSqMXnp3JMbiaVJ6mvoY8=
github.com/pingcap/parser v0.0.0-20200424075042-8222d8b724a4 h1:1dFbm4zVXWvdwjEdyjMlu1PCxnlxK+JfNq+HhbGjDtc=
github.com/pingcap/parser v0.0.0-20200424075042-8222d8b724a4/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4=
github.com/pingcap/parser v0.0.0-20200427031542-879c7bd4f27d h1:iXKcmBOj5v8Vw4jbiWdY0LKyhJinSwqd1Hwyi0NvxBY=
github.com/pingcap/parser v0.0.0-20200427031542-879c7bd4f27d/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4=
github.com/pingcap/parser v0.0.0-20200521064712-8dc0fb6ce6f4 h1:7JQNJ7F9C18FyFGETdmM3WyX6Thm4v1h/7OY6o9ETYU=
github.com/pingcap/parser v0.0.0-20200521064712-8dc0fb6ce6f4/go.mod h1:9v0Edh8IbgjGYW2ArJr19E+bvL8zKahsFp+ixWeId+4=
github.com/pingcap/pd/v4 v4.0.0-rc.1.0.20200422143320-428acd53eba2 h1:JTzYYukREvxVSKW/ncrzNjFitd8snoQ/Xz32pw8i+s8=
github.com/pingcap/pd/v4 v4.0.0-rc.1.0.20200422143320-428acd53eba2/go.mod h1:s+utZtXDznOiL24VK0qGmtoHjjXNsscJx3m1n8cC56s=
github.com/pingcap/sysutil v0.0.0-20200206130906-2bfa6dc40bcd/go.mod h1:EB/852NMQ+aRKioCpToQ94Wl7fktV+FNnxf3CX/TTXI=
Expand Down Expand Up @@ -520,6 +523,8 @@ go.uber.org/zap v1.12.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.13.0/go.mod h1:zwrFLgMcdUuIBviXEYEH1YKNaOBnKXsx2IPda5bBwHM=
go.uber.org/zap v1.14.1 h1:nYDKopTbvAPq/NrUVZwT15y2lpROBiLLyoRTbXOYWOo=
go.uber.org/zap v1.14.1/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
go.uber.org/zap v1.15.0 h1:ZZCA22JRF2gQE5FoNmhmrf7jeJJ2uhqDUNRYKm8dvmM=
go.uber.org/zap v1.15.0/go.mod h1:Mb2vm2krFEG5DV0W9qcHBYFtp/Wku1cvYaqPsS/WYfc=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20181203042331-505ab145d0a9/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
Expand Down
19 changes: 18 additions & 1 deletion planner/core/planbuilder.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ import (
"github.com/pingcap/tidb/store/tikv"
"github.com/pingcap/tidb/table"
"github.com/pingcap/tidb/types"
driver "github.com/pingcap/tidb/types/parser_driver"
"github.com/pingcap/tidb/types/parser_driver"
util2 "github.com/pingcap/tidb/util"
"github.com/pingcap/tidb/util/chunk"
"github.com/pingcap/tidb/util/hint"
Expand All @@ -52,6 +52,7 @@ import (
"github.com/pingcap/tidb/util/set"

"github.com/cznic/mathutil"
"github.com/pingcap/tidb/table/tables"
"go.uber.org/zap"
)

Expand Down Expand Up @@ -1985,6 +1986,22 @@ func (b *PlanBuilder) buildInsert(ctx context.Context, insert *ast.InsertStmt) (
IsReplace: insert.IsReplace,
}.Init(b.ctx)

if tableInfo.GetPartitionInfo() != nil && len(insert.PartitionNames) != 0 {
givenPartitionSets := make(map[int64]struct{}, len(insert.PartitionNames))
// check partition by name.
for _, name := range insert.PartitionNames {
id, err := tables.FindPartitionByName(tableInfo, name.L)
if err != nil {
return nil, err
}
givenPartitionSets[id] = struct{}{}
}
pt := tableInPlan.(table.PartitionedTable)
insertPlan.Table = tables.NewPartitionTableithGivenSets(pt, givenPartitionSets)
} else if len(insert.PartitionNames) != 0 {
return nil, ErrPartitionClauseOnNonpartitioned
}

var authErr error
if b.ctx.GetSessionVars().User != nil {
authErr = ErrTableaccessDenied.GenWithStackByArgs("INSERT", b.ctx.GetSessionVars().User.Hostname,
Expand Down

0 comments on commit 70e94b4

Please sign in to comment.