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

planner/core,binloginfo: add a projection to fix 'delete from join' schema #8805

Merged
merged 10 commits into from
Dec 29, 2018

Conversation

tiancaiamao
Copy link
Contributor

@tiancaiamao tiancaiamao commented Dec 25, 2018

What problem does this PR solve?

CREATE TABLE `b1` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` varchar(50) NOT NULL,
`split_job_id` varchar(30) DEFAULT NULL,
PRIMARY KEY (`id`),
KEY `b1` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_bin

CREATE TABLE `b2` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`job_id` varchar(50) NOT NULL,
`batch_class` varchar(20) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `bu` (`job_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

mysql> insert into b2 (job_id, batch_class) values (2, 'TEST');
Query OK, 1 row affected (0.01 sec)

mysql> insert into b1 (job_id) values (2);
Query OK, 1 row affected (0.00 sec)

mysql> delete from b1 where job_id in (select job_id from b2 where batch_class = 'TEST') or split_job_id in (select job_id from b2 where batch_class = 'TEST');

With binlog on, the last SQL fail like this:

2018/12/24 14:10:22.596 session.go:851: [warning] con:1 schema_ver:20 session error:
2018/12/24 14:10:22.596 session.go:851: [warning] con:1 schema_ver:20 session error: EncodeRow error: data and columnID count not match 5 vs 3
github.com/pingcap/tidb/tablecodec.EncodeRow /home/robi/Code/go/src/github.com/pingcap/tidb/tablecodec/tablecodec.go:229
github.com/pingcap/tidb/table/tables.(*tableCommon).addDeleteBinlog /home/robi/Code/go/src/github.com/pingcap/tidb/table/tables/tables.go:734
github.com/pingcap/tidb/table/tables.(*tableCommon).RemoveRecord /home/robi/Code/go/src/github.com/pingcap/tidb/table/tables/tables.go:688
github.com/pingcap/tidb/executor.(*DeleteExec).removeRow /home/robi/Code/go/src/github.com/pingcap/tidb/executor/delete.go:223
github.com/pingcap/tidb/executor.(*DeleteExec).deleteOneRow /home/robi/Code/go/src/github.com/pingcap/tidb/executor/delete.go:80
github.com/pingcap/tidb/executor.(*DeleteExec).deleteSingleTableByChunk /home/robi/Code/go/src/github.com/pingcap/tidb/executor/delete.go:130
github.com/pingcap/tidb/executor.(*DeleteExec).Next /home/robi/Code/go/src/github.com/pingcap/tidb/executor/delete.go:57
github.com/pingcap/tidb/executor.(*ExecStmt).handleNoDelayExecutor /home/robi/Code/go/src/github.com/pingcap/tidb/executor/adapter.go:296
github.com/pingcap/tidb/executor.(*ExecStmt).Exec /home/robi/Code/go/src/github.com/pingcap/tidb/executor/adapter.go:242
github.com/pingcap/tidb/session.runStmt /home/robi/Code/go/src/github.com/pingcap/tidb/session/tidb.go:195
github.com/pingcap/tidb/session.(*session).executeStatement /home/robi/Code/go/src/github.com/pingcap/tidb/session/session.go:848
github.com/pingcap/tidb/session.(*session).execute /home/robi/Code/go/src/github.com/pingcap/tidb/session/session.go:916
github.com/pingcap/tidb/session.(*session).Execute /home/robi/Code/go/src/github.com/pingcap/tidb/session/session.go:869
github.com/pingcap/tidb/server.(*TiDBContext).Execute /home/robi/Code/go/src/github.com/pingcap/tidb/server/driver_tidb.go:245
github.com/pingcap/tidb/server.(*clientConn).handleQuery /home/robi/Code/go/src/github.com/pingcap/tidb/server/conn.go:922
github.com/pingcap/tidb/server.(*clientConn).dispatch /home/robi/Code/go/src/github.com/pingcap/tidb/server/conn.go:658
github.com/pingcap/tidb/server.(*clientConn).Run /home/robi/Code/go/src/github.com/pingcap/tidb/server/conn.go:502
github.com/pingcap/tidb/server.(*Server).onConn /home/robi/Code/go/src/github.com/pingcap/tidb/server/server.go:324

What is changed and how it works?

The final schema should be the schema of table b1, rather than the schema of join.
Add a projection to the plan to get the correct schema.

Check List

Tests

  • Unit test

This change is Reviewable

'delete from t where a in (select ...) or b in (select ...)'
The correct schema should be the schema of t, rather than the schema of
the join. Add a projection in this case.
@tiancaiamao
Copy link
Contributor Author

PTAL @lysu @winoros

proj.SetSchema(oldSchema.Clone())
p = proj
}

Copy link
Contributor

Choose a reason for hiding this comment

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

Should we add projection for Update as well?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Yes, update have the same problem

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I simply add a projection but the CI failed.
I'll fix delete first, and leave update to somebody else.

Copy link
Member

@winoros winoros left a comment

Choose a reason for hiding this comment

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

lgtm

@winoros winoros added status/LGT1 Indicates that a PR has LGTM 1. type/bugfix This PR fixes a bug. sig/planner SIG: Planner labels Dec 25, 2018
// Add a projection for the following case, otherwise the final schema will be the schema of the join.
// delete from t where a in (select ...) or b in (select ...)
if oldLen := oldSchema.Len(); oldLen != p.Schema().Len() {
proj := LogicalProjection{Exprs: expression.Column2Exprs(p.Schema().Columns[:oldLen])}.Init(b.ctx)
Copy link
Contributor

Choose a reason for hiding this comment

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

it seems to delete target table isn't always the first table, MySQL support delete multiple tables syntax, although I never use that https://dev.mysql.com/doc/refman/5.7/en/delete.html 🤣

Copy link
Member

Choose a reason for hiding this comment

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

Yes, we should consider the case of multi-table deletion.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Delete from A where ... // delete single table
Delete A B ... from ... // delete multiple table
Delete from A B using ... // delete multiple table

Multiple tables case is more complex. This PR will only handle the single table cases.

Let's have a look what's the bug actually:
select from A where A join B ... there is a projection on A join B
but for
delete from A where A join B ..., the projection is missing.

Copy link
Member

Choose a reason for hiding this comment

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

What output should it be if it's a multiple tables deleting?

@shenli
Copy link
Member

shenli commented Dec 26, 2018

@tiancaiamao Please address the comments.

@tiancaiamao
Copy link
Contributor Author

/run-all-tests

@tiancaiamao
Copy link
Contributor Author

/run-all-tests

@tiancaiamao
Copy link
Contributor Author

/run-all-tests

@tiancaiamao
Copy link
Contributor Author

/run-unit-test

1 similar comment
@eurekaka
Copy link
Contributor

/run-unit-test

@tiancaiamao
Copy link
Contributor Author

/run-all-tests

@lysu
Copy link
Contributor

lysu commented Dec 29, 2018

LGTM.

and it's a little stranger, delete by subquery eliminate unused column by projection, but delete multiple tables eliminate unused column in deleteMultiTablesByChunk.

@lysu lysu added status/LGT2 Indicates that a PR has LGTM 2. and removed status/LGT1 Indicates that a PR has LGTM 1. labels Dec 29, 2018
@tiancaiamao
Copy link
Contributor Author

/run-unit-test

@tiancaiamao tiancaiamao merged commit 599b9eb into pingcap:master Dec 29, 2018
@tiancaiamao tiancaiamao deleted the delete-schema branch December 29, 2018 07:41
yu34po pushed a commit to yu34po/tidb that referenced this pull request Jan 2, 2019
…chema (pingcap#8805)

'delete from t where a in (select ...) or b in (select ...)'
The correct schema should be the schema of t, rather than the schema of
the join. Add a projection in this case.
@tshqin
Copy link
Contributor

tshqin commented May 25, 2019

need a cherry pick to 2.1 version

tiancaiamao added a commit to tiancaiamao/tidb that referenced this pull request May 25, 2019
…chema (pingcap#8805)

'delete from t where a in (select ...) or b in (select ...)'
The correct schema should be the schema of t, rather than the schema of
the join. Add a projection in this case.
ngaut pushed a commit that referenced this pull request May 26, 2019
…chema (#8805) (#10595)

'delete from t where a in (select ...) or b in (select ...)'
The correct schema should be the schema of t, rather than the schema of
the join. Add a projection in this case.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
sig/planner SIG: Planner 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.

7 participants