Skip to content

Commit

Permalink
dml: fix index column offset beyond the range (#25699)
Browse files Browse the repository at this point in the history
  • Loading branch information
AilinKid authored Jul 15, 2021
1 parent 2412437 commit d05b6f4
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 11 deletions.
28 changes: 25 additions & 3 deletions ddl/db_change_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,28 @@ func (s *testStateChangeSuite) TestDeleteOnly(c *C) {
s.runTestInSchemaState(c, model.StateDeleteOnly, true, dropColumnSQL, sqls, query)
}

// TestDeleteOnlyForDropColumnWithIndexes test for delete data when a middle-state column with indexes in it.
func (s *testStateChangeSuite) TestDeleteOnlyForDropColumnWithIndexes(c *C) {
tk := testkit.NewTestKit(c, s.store)
tk.MustExec("use test_db_state")
sqls := make([]sqlWithErr, 2)
sqls[0] = sqlWithErr{"delete from t1", nil}
sqls[1] = sqlWithErr{"delete from t1 where b=1", errors.Errorf("[planner:1054]Unknown column 'b' in 'where clause'")}
prepare := func() {
tk.MustExec("drop table if exists t1")
tk.MustExec("create table t1(a int key, b int, c int, index idx(b));")
tk.MustExec("insert into t1 values(1,1,1);")
}
prepare()
dropColumnSQL := "alter table t1 drop column b"
query := &expectQuery{sql: "select * from t1;", rows: []string{}}
s.runTestInSchemaState(c, model.StateWriteOnly, true, dropColumnSQL, sqls, query)
prepare()
s.runTestInSchemaState(c, model.StateDeleteOnly, true, dropColumnSQL, sqls, query)
prepare()
s.runTestInSchemaState(c, model.StateDeleteReorganization, true, dropColumnSQL, sqls, query)
}

// TestDeleteOnlyForDropExpressionIndex tests for deleting data when the hidden column is delete-only state.
func (s *serialTestStateChangeSuite) TestDeleteOnlyForDropExpressionIndex(c *C) {
originalVal := config.GetGlobalConfig().Experimental.AllowsExpressionIndex
Expand Down Expand Up @@ -851,9 +873,9 @@ func (s *testStateChangeSuiteBase) runTestInSchemaState(c *C, state model.Schema
return
}
for _, sqlWithErr := range sqlWithErrs {
_, err = se.Execute(context.Background(), sqlWithErr.sql)
if !terror.ErrorEqual(err, sqlWithErr.expectErr) {
checkErr = errors.Errorf("sql: %s, expect err: %v, got err: %v", sqlWithErr.sql, sqlWithErr.expectErr, err)
_, err1 := se.Execute(context.Background(), sqlWithErr.sql)
if !terror.ErrorEqual(err1, sqlWithErr.expectErr) {
checkErr = errors.Errorf("sql: %s, expect err: %v, got err: %v", sqlWithErr.sql, sqlWithErr.expectErr, err1)
break
}
}
Expand Down
5 changes: 5 additions & 0 deletions infoschema/perfschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@ func (vt *perfSchemaTable) WritableCols() []*table.Column {
return vt.cols
}

// DeletableCols implements table.Table Type interface.
func (vt *perfSchemaTable) DeletableCols() []*table.Column {
return vt.cols
}

// FullHiddenColsAndVisibleCols implements table FullHiddenColsAndVisibleCols interface.
func (vt *perfSchemaTable) FullHiddenColsAndVisibleCols() []*table.Column {
return vt.cols
Expand Down
10 changes: 10 additions & 0 deletions infoschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -1891,6 +1891,11 @@ func (it *infoschemaTable) WritableCols() []*table.Column {
return it.cols
}

// DeletableCols implements table.Table WritableCols interface.
func (it *infoschemaTable) DeletableCols() []*table.Column {
return it.cols
}

// FullHiddenColsAndVisibleCols implements table FullHiddenColsAndVisibleCols interface.
func (it *infoschemaTable) FullHiddenColsAndVisibleCols() []*table.Column {
return it.cols
Expand Down Expand Up @@ -1969,6 +1974,11 @@ func (vt *VirtualTable) WritableCols() []*table.Column {
return nil
}

// DeletableCols implements table.Table WritableCols interface.
func (vt *VirtualTable) DeletableCols() []*table.Column {
return nil
}

// FullHiddenColsAndVisibleCols implements table FullHiddenColsAndVisibleCols interface.
func (vt *VirtualTable) FullHiddenColsAndVisibleCols() []*table.Column {
return nil
Expand Down
18 changes: 10 additions & 8 deletions planner/core/logical_plan_builder.go
Original file line number Diff line number Diff line change
Expand Up @@ -3926,8 +3926,8 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as
// If we use tbl.Cols() here, the update statement, will ignore the col `c`, and the data `3` will lost.
columns = tbl.WritableCols()
} else if b.inDeleteStmt {
// All hidden columns are needed because we need to delete the expression index that consists of hidden columns.
columns = tbl.FullHiddenColsAndVisibleCols()
// DeletableCols returns all columns of the table in deletable states.
columns = tbl.DeletableCols()
} else {
columns = tbl.Cols()
}
Expand Down Expand Up @@ -3998,12 +3998,13 @@ func (b *PlanBuilder) buildDataSource(ctx context.Context, tn *ast.TableName, as
for i, col := range columns {
ds.Columns = append(ds.Columns, col.ToInfo())
names = append(names, &types.FieldName{
DBName: dbName,
TblName: tableInfo.Name,
ColName: col.Name,
OrigTblName: tableInfo.Name,
OrigColName: col.Name,
Hidden: col.Hidden,
DBName: dbName,
TblName: tableInfo.Name,
ColName: col.Name,
OrigTblName: tableInfo.Name,
OrigColName: col.Name,
Hidden: col.Hidden,
// For update statement and delete statement, internal version should see the special middle state column, while user doesn't.
NotExplicitUsable: col.State != model.StatePublic,
})
newCol := &expression.Column{
Expand Down Expand Up @@ -4887,6 +4888,7 @@ func (b *PlanBuilder) buildDelete(ctx context.Context, delete *ast.DeleteStmt) (
oldSchema := p.Schema()
oldLen := oldSchema.Len()

// For explicit column usage, should use the all-public columns.
if delete.Where != nil {
p, err = b.buildSelection(ctx, p, delete.Where, nil)
if err != nil {
Expand Down
4 changes: 4 additions & 0 deletions table/table.go
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,10 @@ type columnAPI interface {
// Writable states includes Public, WriteOnly, WriteOnlyReorganization.
WritableCols() []*Column

// DeletableCols returns columns of the table in deletable states.
// Deletable states includes Public, WriteOnly, WriteOnlyReorganization, DeleteOnly, DeleteReorganization.
DeletableCols() []*Column

// FullHiddenColsAndVisibleCols returns hidden columns in all states and unhidden columns in public states.
FullHiddenColsAndVisibleCols() []*Column
}
Expand Down
5 changes: 5 additions & 0 deletions table/tables/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -285,6 +285,11 @@ func (t *TableCommon) WritableCols() []*table.Column {
return writableColumns
}

// DeletableCols implements table DeletableCols interface.
func (t *TableCommon) DeletableCols() []*table.Column {
return t.Columns
}

// FullHiddenColsAndVisibleCols implements table FullHiddenColsAndVisibleCols interface.
func (t *TableCommon) FullHiddenColsAndVisibleCols() []*table.Column {
if len(t.FullHiddenColsAndVisibleColumns) > 0 {
Expand Down

0 comments on commit d05b6f4

Please sign in to comment.