Skip to content

Commit cfaa8ff

Browse files
committed
avoid running queries on the WriteOnly state table
Signed-off-by: Yang Keao <[email protected]>
1 parent fef43c5 commit cfaa8ff

File tree

2 files changed

+59
-0
lines changed

2 files changed

+59
-0
lines changed

pkg/ddl/foreign_key_test.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -402,3 +402,41 @@ func TestAddForeignKey3(t *testing.T) {
402402
tk.MustQuery("select * from t1 order by id").Check(testkit.Rows("1 1", "2 2", "3 3"))
403403
tk.MustQuery("select * from t2 order by id").Check(testkit.Rows("1 1", "2 2", "3 3"))
404404
}
405+
406+
func TestForeignKeyInWriteOnlyMode(t *testing.T) {
407+
store := testkit.CreateMockStore(t)
408+
tk := testkit.NewTestKit(t, store)
409+
tk.MustExec("use test")
410+
411+
tkDDL := testkit.NewTestKit(t, store)
412+
tkDDL.MustExec("use test")
413+
tkDDL.MustExec("create table parent (id int key)")
414+
tkDDL.MustExec("insert into parent values(1)")
415+
416+
var notExistErrs []error
417+
testfailpoint.EnableCall(t, "github.com/pingcap/tidb/pkg/ddl/onJobRunBefore", func(job *model.Job) {
418+
if job.Type == model.ActionCreateTable && job.TableName == "child" {
419+
if job.SchemaState == model.StateWriteOnly {
420+
// tk with the latest schema will insert data into child
421+
_, err := tk.Exec("insert into child values (1, 1)")
422+
notExistErrs = append(notExistErrs, err)
423+
_, err = tk.Exec("update child set id = 2 where id = 1")
424+
notExistErrs = append(notExistErrs, err)
425+
_, err = tk.Exec("delete from child where id = 1")
426+
notExistErrs = append(notExistErrs, err)
427+
_, err = tk.Exec("delete child from child inner join parent where child.pid = parent.id")
428+
notExistErrs = append(notExistErrs, err)
429+
_, err = tk.Exec("delete parent from child inner join parent where child.pid = parent.id")
430+
notExistErrs = append(notExistErrs, err)
431+
}
432+
}
433+
})
434+
tkDDL.MustExec("create table child (id int, pid int, index idx_pid(pid), foreign key (pid) references parent(id) on delete cascade);")
435+
436+
testfailpoint.Disable(t, "github.com/pingcap/tidb/pkg/ddl/onJobRunBefore")
437+
438+
for _, err := range notExistErrs {
439+
require.Error(t, err)
440+
require.Contains(t, err.Error(), "Table 'test.child' doesn't exist")
441+
}
442+
}

pkg/planner/core/preprocess.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1634,6 +1634,10 @@ func (p *preprocessor) handleTableName(tn *ast.TableName) {
16341634
return
16351635
}
16361636
}
1637+
if err := p.checkTableVisible(tableInfo); err != nil {
1638+
p.err = err
1639+
return
1640+
}
16371641
p.resolveCtx.AddTableName(&resolve.TableNameW{
16381642
TableName: tn,
16391643
DBInfo: dbInfo,
@@ -1975,3 +1979,20 @@ func (p *preprocessor) skipLockMDL() bool {
19751979
// skip lock mdl for ANALYZE statement.
19761980
return p.flag&inImportInto > 0 || p.flag&inAnalyze > 0
19771981
}
1982+
1983+
// checkTableVisible returns an `ErrTableNotExists` error if the table is not visible (in None or WriteOnly state).
1984+
func (p *preprocessor) checkTableVisible(tblInfo *model.TableInfo) error {
1985+
is := p.ensureInfoSchema()
1986+
1987+
if tblInfo.State != model.StatePublic {
1988+
schemaName := "unknown"
1989+
schema, ok := infoschema.SchemaByTable(is, tblInfo)
1990+
if ok {
1991+
// theoretically, this should always happen
1992+
schemaName = schema.Name.O
1993+
}
1994+
return infoschema.ErrTableNotExists.FastGenByArgs(schemaName, tblInfo.Name.O)
1995+
}
1996+
1997+
return nil
1998+
}

0 commit comments

Comments
 (0)