-
Notifications
You must be signed in to change notification settings - Fork 5.8k
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
ddl, planner, executor: implement CREATE TABLE ... SELECT #7787
Conversation
98bbb05
to
73afbf2
Compare
@bb7133 Great work! thanks |
1b04937
to
fb78958
Compare
Thank you for all the helps and advices! |
@bb7133 Friendly reminding. You can use |
fb78958
to
b7bddf6
Compare
I didn't know this feature before, thank you! |
ddl/ddl_api.go
Outdated
@@ -965,10 +966,10 @@ func (d *ddl) CreateTable(ctx sessionctx.Context, s *ast.CreateTableStmt) (err e | |||
|
|||
// table exists, but if_not_exists flags is true, so we ignore this error. | |||
if infoschema.ErrTableExists.Equal(err) && s.IfNotExists { | |||
return nil | |||
return tbInfo.ID, nil |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If table exists, we need to execute the insertion of create-select?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Of course we shouldn't, I will fix this, thanks!
Hi @winkyao, thanks for all the reviews! I was just too busy to deal with all of them in the last few days. Hope I can address them soon. |
436bd4e
to
4d4d630
Compare
executor/builder.go
Outdated
@@ -656,12 +660,74 @@ func (b *executorBuilder) buildRevoke(revoke *ast.RevokeStmt) Executor { | |||
} | |||
|
|||
func (b *executorBuilder) buildDDL(v *plannercore.DDL) Executor { | |||
e := &DDLExec{ | |||
if b.ctx.GetSessionVars().CreateTableInsertingID != 0 { | |||
// in a 'inserting data from select' state of creating table. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you add more comments here, to explain why we implement create select so weird? And add a TODO.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, thanks!
executor/builder.go
Outdated
// The operation of the minus 1 to make sure that the current value doesn't be used, | ||
// the next Alloc operation will get this value. | ||
// Its behavior is consistent with MySQL. | ||
if err = tbl.RebaseAutoID(nil, tbInfo.AutoIncID-1, false); err != nil { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The auto increment id will be rebased after the table create finished, create select rebase it here, so if the create_select is true, we should not set auto-id in https://github.com/pingcap/tidb/blob/master/ddl/ddl_api.go#L964?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could we add a test case like create table auto_increment= xxx select
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- You're right, I didn't treat here carefully, the current codes just work because
Allocator
.Rebase
prevented base id rolling back. - There is a test case already, but now I think it can be enhanced.
Thanks for the review
6cf0fb8
to
b991ee9
Compare
@winkyao comments addressed, PTAL, thank you for your review! |
c1f90a5
to
3b40c98
Compare
ddl/ddl.go
Outdated
@@ -540,6 +543,7 @@ func (d *ddl) doDDLJob(ctx sessionctx.Context, job *model.Job) error { | |||
// If a job is a history job, the state must be JobSynced or JobCancel. | |||
if historyJob.IsSynced() { | |||
log.Infof("[ddl] DDL job ID:%d is finished", jobID) | |||
ctx.GetSessionVars().StmtCtx.AddAffectedRows(uint64(historyJob.GetRowCount())) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Watch out, add index also use job.RowCount
. So this will make add index
return xx row affected.
In Mysql:
mysql root@127.0.0.1:test> create table t1 (a int);
Query OK, 0 rows affected
Time: 0.010s
mysql root@127.0.0.1:test> insert into t1 values (0),(1),(2),(3),(4),(5);
Query OK, 6 rows affected
Time: 0.001s
mysql root@127.0.0.1:test> alter table t1 add index idx(a);
Query OK, 0 rows affected
Time: 0.008s
mysql root@127.0.0.1:test> create table t2 select a from t1;
Query OK, 6 rows affected
Time: 0.007s
In This PR:
mysql root@127.0.0.1:test> create table t1 (a int);
Query OK, 0 rows affected
Time: 0.008s
mysql root@127.0.0.1:test> insert into t1 values (0),(1),(2),(3),(4),(5);
Query OK, 6 rows affected
Time: 0.001s
mysql root@127.0.0.1:test> alter table t1 add index idx(a);
Query OK, 6 rows affected
Time: 0.016s
mysql root@127.0.0.1:test> create table t2 select a from t1;
Query OK, 6 rows affected
Time: 0.012s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Sure, thank you!
ddl/delete_range.go
Outdated
@@ -243,6 +243,25 @@ func insertJobIntoDeleteRangeTable(ctx sessionctx.Context, job *model.Job) error | |||
startKey = tablecodec.EncodeTablePrefix(tableID) | |||
endKey := tablecodec.EncodeTablePrefix(tableID + 1) | |||
return doInsert(s, job.ID, tableID, startKey, endKey, now) | |||
case model.ActionCreateTable: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can we change the job Args to same with drop table
? Then we can reuse the drop table
code here. You can refer to create index
rolling back. But create index
does't reuse the drop index
code here is for compatibility. create table
rolling back doesn't have compatibility problem.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Or create a function to remove redundant code in here and drop table
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for the tips, let me refine the code
ddl/table.go
Outdated
@@ -477,6 +523,7 @@ func updateVersionAndTableInfo(t *meta.Meta, job *model.Job, tblInfo *model.Tabl | |||
return ver, t.UpdateTable(job.SchemaID, tblInfo) | |||
} | |||
|
|||
// onAddTablePartition handle ActionAddTablePartition DDL job |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
%s/handle/handles
mockTablePlan := LogicalTableDual{}.Init(b.ctx) | ||
mockTablePlan.SetSchema(expression.NewSchema(mockExprs...)) | ||
|
||
genCols, err := b.resolveGeneratedColumns(mockColumns, nil, mockTablePlan) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
In mysql:
mysql root@127.0.0.1:test> create table t1 (a int);
Query OK, 0 rows affected
Time: 0.011s
mysql root@127.0.0.1:test> insert into t1 values (0),(1),(2),(3),(4),(5);
Query OK, 6 rows affected
Time: 0.001s
mysql root@127.0.0.1:test> create table t2 (a int key, b int as (a*2)) select a,a+1 as b from t1;
(3105, u"The value specified for generated column 'b' in table 't2' is not allowed.")
In TiDB this PR:
mysql root@127.0.0.1:test> create table t1 (a int);
Query OK, 0 rows affected
Time: 0.005s
mysql root@127.0.0.1:test> insert into t1 values (0),(1),(2),(3),(4),(5);
Query OK, 6 rows affected
Time: 0.004s
mysql root@127.0.0.1:test> create table t2 (a int key, b int as (a*2)) select a,a+1 as b from t1;
Query OK, 6 rows affected
Time: 0.014s
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
fixed, thanks
3b40c98
to
3f7dec5
Compare
fix pingcap#4754, fix pingcap#3839
1. fixed some codestyles 2. added more comments 3. changed the mechnism to insert data(from session server to ddl owner) 4. added support for generated columns 5. added more tests
1. refactor CreateTeableInsertExec to re-use current executors 2. added more test cases
3f7dec5
to
e11b04a
Compare
Codecov Report
@@ Coverage Diff @@
## master #7787 +/- ##
==========================================
- Coverage 67.14% 67.03% -0.11%
==========================================
Files 372 373 +1
Lines 76974 77323 +349
==========================================
+ Hits 51682 51837 +155
- Misses 20661 20835 +174
- Partials 4631 4651 +20
Continue to review full report at Codecov.
|
1. fix a bug inserting data into generated columns when creating table 2. fix a 'affected rows' count bug for ddl job 3. refined 'ActionCreateTable' code in delete_range.go 4. fix merge conflict
e11b04a
to
ae22d31
Compare
@crazycs520 PTAL, thank you! |
Now it's very, very difficult to resolve the conflicts from a long commit list. I will close this PR and re-submit a new one. Thanks for the help @winkyao @crazycs520 |
What problem does this PR solve?
Implement 'CREATE TALBE ... SELECT' syntax
What is changed and how it works?
Please check the this doc for the design of this PR: https://docs.google.com/document/d/116QWf7AOQKBCcB-oMXV6mxB8sfdo5NOnEulwr_8_yJQ/edit?usp=sharing
Check List
Tests
Code changes
Side effects
Related changes
Related Issues/PR
Others
The design/implementation in this PR is with flaws: 'CREATE TABLE ... SELECT' is not actually one transaction. Please evaluate whether this is acceptable: if not, I will try to implement the 'alternative solution'(described in the design doc) in the future.
This change is