Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

plan: fix a bug when alter table drop column meets insert #5790

Merged
merged 7 commits into from
Feb 6, 2018

Conversation

jackysp
Copy link
Member

@jackysp jackysp commented Feb 5, 2018

create table t (i int, j int);

session 1:

alter table t drop column j;

session 2:

insert into t set i = 1, j = 1;

could panic, due to TiDB save the column name as a map in buildInsert. PTAL @zimulala @hicqu

@shenli
Copy link
Member

shenli commented Feb 5, 2018

Could you add a test case?

@shenli
Copy link
Member

shenli commented Feb 5, 2018

/run-all-tests

@jackysp jackysp changed the title plan: fix a bug when alter table add column meets insert plan: fix a bug when alter table drop column meets insert Feb 5, 2018
@winkyao
Copy link
Contributor

winkyao commented Feb 5, 2018

Could you add the original schrodinger test case to unit test?

@@ -878,8 +890,8 @@ func (b *planBuilder) buildInsert(insert *ast.InsertStmt) Plan {
return nil
}
// Check set list contains generated column or not.
if columnByName[assign.Column.Name.L].IsGenerated() {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it panic here?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it does panic here, because the assign.Column.Name.L is not in columnByName, I think, we can just skip it here( check whether the value is null is ok). No need to add checkGeneratedColumn function to iterator the columns array every time.

Copy link
Member Author

@jackysp jackysp Feb 5, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think it is a good solution to skip it directly. We should not use columnByName to avoid potential bugs. @winkyao

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is not potential bugs, actually it is expected that there is some inserting column not in columnByName. We should not reduce the performance here. @jackysp

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

line 796 check the situation, but here not, so it panic.

if column.IsGenerated() {
b.err = ErrBadGeneratedColumn.GenByArgs(col.Name.O, tableInfo.Name.O)
if err := checkGeneratedColumn(col, insertPlan.Table); err != nil {
if terror.ErrorEqual(err, ErrBadGeneratedColumn) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why not return Can't find column... error?

@winkyao winkyao added the type/bugfix This PR fixes a bug. label Feb 5, 2018
@coocood
Copy link
Member

coocood commented Feb 5, 2018

@jackysp
The root cause of this bug is that TableInfo2SchemaWithDBName returns a schema with non-public column, so the schema can find the assignment column but the map columnByName can not. columnByName is build from Table.Cols() which only returns public columns.

@winkyao
Copy link
Contributor

winkyao commented Feb 6, 2018

@jackysp you can use gofail to add some test

@@ -285,6 +285,9 @@ func TableInfo2SchemaWithDBName(dbName model.CIStr, tbl *model.TableInfo) *Schem
func ColumnInfos2ColumnsWithDBName(dbName, tblName model.CIStr, colInfos []*model.ColumnInfo) []*Column {
columns := make([]*Column, 0, len(colInfos))
for i, col := range colInfos {
if col.State != model.StatePublic {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

what about write only column? @zimulala PTAL

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If the column is given by the client, we need the Public column.

@jackysp
Copy link
Member Author

jackysp commented Feb 6, 2018

No pause support in gofail @winkyao , I've add a concurrency test, it will panic without the bug fix.

@jackysp
Copy link
Member Author

jackysp commented Feb 6, 2018

PTAL @shenli @zimulala @coocood

Copy link
Contributor

@winkyao winkyao left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

coocood
coocood previously approved these changes Feb 6, 2018
Copy link
Member

@coocood coocood left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@@ -988,6 +995,28 @@ LOOP:
c.Assert(count, Greater, int64(0))
}

func (s *testDBSuite) testDropColumn2(c *C) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a comment for this test.

@jackysp
Copy link
Member Author

jackysp commented Feb 6, 2018

/run-all-tests

@jackysp
Copy link
Member Author

jackysp commented Feb 6, 2018

PTAL @zimulala

@zimulala zimulala added the status/LGT2 Indicates that a PR has LGTM 2. label Feb 6, 2018
@winoros winoros merged commit 26d4887 into pingcap:master Feb 6, 2018
jackysp added a commit to jackysp/tidb that referenced this pull request Feb 6, 2018
@jackysp jackysp deleted the insert_panic branch April 4, 2018 05:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
status/LGT2 Indicates that a PR has LGTM 2. type/bugfix This PR fixes a bug.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

6 participants