-
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: fix invalid index on multi-layer virtual columns #11260
ddl: fix invalid index on multi-layer virtual columns #11260
Conversation
Codecov Report
@@ Coverage Diff @@
## master #11260 +/- ##
===========================================
Coverage 81.4063% 81.4063%
===========================================
Files 423 423
Lines 90816 90816
===========================================
Hits 73930 73930
Misses 11573 11573
Partials 5313 5313 |
/run-integration-tests |
@crazycs520 @bb7133 @zimulala PTAL~ |
Excellent PR description! @tangenta |
util/rowDecoder/decoder.go
Outdated
} | ||
return v | ||
case *expression.ScalarFunction: | ||
if v.FuncName.L == ast.Cast { |
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 handle CAST
in this special way? I don't get the point from expression.ColumnSubstitute
, neither from here.
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.
Actually, I am not sure. The removal of them does NOT fail the integration test.
util/rowDecoder/decoder.go
Outdated
// SubstituteGenColsInDecodeColMap substitutes generated columns in every expression in decodeColMap | ||
// with non-generated one by looking up decodeColMap. | ||
func SubstituteGenColsInDecodeColMap(decodeColMap map[int64]Column) { | ||
// Sort columns by ID in ascending order. |
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.
Please Add comment why you need sort here. I think you have an assumption here.
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.
@crazycs520 I think line 150 does explain it. Do you have any suggestions?
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 reason is here: (https://dev.mysql.com/doc/refman/5.7/en/create-table-generated-columns.html)
A generated column definition can refer to other generated columns, but only those occurring earlier in the table definition. A generated column definition can refer to any base (nongenerated) column in the table whether its definition occurs earlier or later.
Is it possible that the order of column ID is not the order of columns shown in the table definition? Using column ID is a bit risky here. @crazycs520 @tangenta
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.
@bb7133 You are right. I have found a test case that violates this assumption. I think
sorting by table.Column.Offset
is the correct choice.
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.
@bb7133 You are right. I have found a test case that violates this assumption. I think
sorting bytable.Column.Offset
is the correct choice.
Good job, would you please show the case here?
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.
create table t (a int, c int as (a + 1));
alter table t add column b int as (a + 1) after a;
Here the ID of column a
, b
and c
is 1
, 3
and 2
respectively.
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 looks like you need fix bug:#11365 first.
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
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
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.
/run-all-tests |
/run-all-tests |
@tangenta Please fix the CI problem. |
/run-unit-test |
cherry pick to release-3.0 failed |
cherry pick to release-2.1 failed |
What problem does this PR solve?
Fix #11139.
What is changed and how it works?
When a generated column depends on another generated column, like
c -> b -> a
, the old implementation fails to backfill the existing row data when creating an index onc
.In
makeupDecodeColMap()
, adecodeColMap
is used to save the information about a column, containingcolumn id -> table.column & generated expression
.In index-value-backfill period,
decodeColMap
can be used to fetch row values.For example,
When creating an index on
c
, the old implementation ofmakeupDecodeColMap()
builds adecodeColMap
likewithout considering whether b is a generated column.
In this PR, to build a
decodeColMap
, below three steps is needed:expression.Column
in map with another expression, until no generated column in GenExpr field of every value in map.Step2 substitute generated columns in a columnID-ascending order, ensuring that no unresolved generated column exists.
The map building process in the above example:
Step 1,
Step 2,
Step 3,
Check List
Tests
Code changes
Side effects
Related changes