-
Notifications
You must be signed in to change notification settings - Fork 5.9k
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: Fix generated column can refer only to generated columns defined prior to it. #11549
Conversation
/rebuild |
/run-all-tests |
d11b415
to
cdfd042
Compare
Codecov Report
@@ Coverage Diff @@
## master #11549 +/- ##
================================================
- Coverage 81.8655% 81.2079% -0.6577%
================================================
Files 427 426 -1
Lines 94759 91874 -2885
================================================
- Hits 77575 74609 -2966
- Misses 11830 11895 +65
- Partials 5354 5370 +16 |
There is an implement for detecting if there is a generated column refer to another generated column occurring earlier in the table. Could we multiplex this function? Line 836 in e3c9abd
Lines 38 to 42 in 1c43f55
|
ddl/db_integration_test.go
Outdated
rs.Close() | ||
} | ||
c.Assert(err, NotNil) | ||
c.Assert(err.Error(), Equals, "[ddl:1054]Unknown column 'f' in 'generated column function'") |
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.
Would you please consider using assertErrorCode()
?
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.
Would you please consider using
assertErrorCode()
?
Addressed @tangenta
executor/ddl_test.go
Outdated
_, err = tk.Exec("alter table t add column(e int as (c+1))") | ||
c.Assert(err, IsNil) | ||
} | ||
|
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.
Why do we need to test the same case twice?
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.
Why do we need to test the same case twice?
Addressed, PTAL
Thx very much. I've changed it: PTAL |
bd67d0a
to
6a89724
Compare
Addressed @Deardrops |
ddl/generated_column.go
Outdated
_, ok := dependCols[col.Name.L] | ||
if col.Offset >= pos && ok && col.IsGenerated() { | ||
// Generated column can refer only to generated columns defined prior to it. | ||
return errGeneratedColumnNonPrior.GenWithStackByArgs() |
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 _, ok := dependCols[col.Name.L]; ok {
if col.IsGenerated() && col.Offset >= pos {
// Generated column can refer only to generated columns defined prior to it.
return errGeneratedColumnNonPrior.GenWithStackByArgs()
}
}
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.
Addressed
if pos == nil { | ||
return position, nil | ||
} | ||
if pos.Tp == ast.ColumnPositionFirst { |
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.
suggestion: changing to select ... case ...
pattern, for better readability.
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.
It handles like ddl/column.103 when in ddl woker.
ddl/generated_column.go
Outdated
@@ -50,10 +50,28 @@ func verifyColumnGeneration(colName2Generation map[string]columnGenerationInDDL, | |||
return nil | |||
} | |||
|
|||
// verifyColumnGenerationSingle is for ADD GENERATED COLUMN, we just need verify one column itself. | |||
func verifyColumnGenerationSingle(dependCols map[string]struct{}, cols []*table.Column, position *ast.ColumnPosition) error { |
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 first parameter of this function is dependCols
, but when call this function, you passed the parameter named duplicateColNames
, is them same?
https://github.com/pingcap/tidb/blob/a7cf2762510cb1f4efd14d6ddd1ae08558ded4e8/ddl/ddl_api.go#L2113
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.
Same. Since dependCols
will change in checkDependedColExist
, so I make it copy.
Parameter Addressed.
/run-all-tests |
1700abd
to
87dfdb3
Compare
LGTM |
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.
LGTM
ddl/ddl_api.go
Outdated
@@ -2101,8 +2100,17 @@ func (d *ddl) AddColumn(ctx sessionctx.Context, ti ast.Ident, spec *ast.AlterTab | |||
if err = checkAutoIncrementRef(specNewColumn.Name.Name.L, dependColNames, t.Meta()); err != nil { | |||
return errors.Trace(err) | |||
} | |||
duplicateColNames := make(map[string]struct{}) |
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.
Make map with capacity.
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.
Addressed.
ddl/generated_column.go
Outdated
// findPositionRelativeColumn return a pos relative to added generated column position | ||
func findPositionRelativeColumn(cols []*table.Column, pos *ast.ColumnPosition) (int, error) { | ||
position := len(cols) | ||
// get column position default is append behind |
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.
// get column position default is append behind | |
// get column position default is append behind |
What does this comment mean? I'm confused
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.
Addressed.
It's should be: Get column position, the default is cols's length means appending behind.
ddl/generated_column.go
Outdated
if col == nil { | ||
return -1, ErrBadField.GenWithStackByArgs(pos.RelativeColumn, "generated column function") | ||
} | ||
// Insert position is after the mentioned column. |
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.
position
cannot be after a column
, you can say 'Inserted column is after the mentioned column'.
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.
Addressed. Yes, shouldn't be a verb here.
6f1fbc8
to
f5f1817
Compare
c99a167
to
396ef77
Compare
/run-all-tests |
cherry pick to release-3.0 failed |
cherry pick to release-2.1 failed |
What problem does this PR solve?
This PR tries to solve the following bug that caused by the order of generated columns and non-generated columns:
TiDB master:
In MySQL 5.7 & 8.0:
Before putting add generated column to ddl job, computing the generated column offset itself and judging the relation with depended generated column offset as well.
What is changed and how it works?
Find the generated column offset itself in func
findPositionRelativeColumn
judge the relation with depended generated column offset in func
checkDependedColValid
Check List
Tests