Add VisibilityBitmap to TableMapEvent in replication#813
Conversation
VisibilityBitmap to TableMapEvent for MySQL 8.0.23+ Invisible…VisibilityBitmap to TableMapEvent in replication
VisibilityBitmap to TableMapEvent in replication|
@lance6716 |
I will take a look some hours later. Thanks for your PR 😄 |
… Columns Changes: - `TableMapEvent.VisibilityBitmap` `VisibilityBitmap` is a bitmap where each bit represents the visibility of a corresponding column in a table. If a bit is set, it indicates that the corresponding column is NOT an invinsible column. Invisible column was introduced in MySQL version 8.0.23. - `TableMapEvent.VisibilityMap` `VisibilityMap` lists boolean values of which is true if column of the same index is NOT an invisible column. Co-authored-by: sean <sean.k1@kakaoent.com>
b2e8633 to
ccabd26
Compare
|
I added a co-author. |
replication/row_event.go
Outdated
| p := 0 | ||
| ret := make(map[int]bool) | ||
| for i := 0; i < int(e.ColumnCount); i++ { | ||
| ret[i] = e.VisibilityBitmap[p/8]&(1<<uint(7-p%8)) != 0 |
There was a problem hiding this comment.
nit: Maybe it's a little easier to understand the original code with countdown instead of 1<<uint(7-p%8)
There was a problem hiding this comment.
@atercattus
I appreciate your review. Also, I agree with you and I can get this fixed.
Actually VisibilityMap is copy and paste of existing UnsignedMap. Should I fix UnsignedMap too?
I could create a separate PR it if it seems irrelevant to this PR.
There was a problem hiding this comment.
Oh. @lance6716 what do you think about this? Apply the Boy Scout Rule or not?
There was a problem hiding this comment.
If we decide to improve, the code will look like below.
func (e *TableMapEvent) VisibilityMap() map[int]bool {
if len(e.VisibilityBitmap) == 0 {
return nil
}
ret := make(map[int]bool)
for _, field := range e.VisibilityBitmap {
for c, i := 0x80, 0; c != 0; c, i = c>>1, i+1 {
ret[i] = field&byte(c) != 0
}
}
return ret
}There was a problem hiding this comment.
The old code is really not easy to understand 😢 I also hope we start to improve the readability. As for UnsignedMap, I'm OK that you also modify it in this PR or another PR. WDYT @atercattus
Your new code snippet seems not optimal. The status of i should be kept when iterate bytes of VisibilityBitmap. And we can early stop when the column count is not a multiple of 8 (though the original code seems not optimize about this). Maybe we can
...
i := 0
for e.VisibilityBitmap {
for c := 0x80; ... {
ret[i] = ...
i++
if i >= e.ColumnCount { return }
}
}
...
Welcome to find different code
There was a problem hiding this comment.
My bad. i should indeed be initialized outside of the inner loop.
replication/row_event.go
Outdated
| p := 0 | ||
| ret := make(map[int]bool) | ||
| for i := 0; i < int(e.ColumnCount); i++ { | ||
| ret[i] = e.VisibilityBitmap[p/8]&(1<<uint(7-p%8)) != 0 |
There was a problem hiding this comment.
The old code is really not easy to understand 😢 I also hope we start to improve the readability. As for UnsignedMap, I'm OK that you also modify it in this PR or another PR. WDYT @atercattus
Your new code snippet seems not optimal. The status of i should be kept when iterate bytes of VisibilityBitmap. And we can early stop when the column count is not a multiple of 8 (though the original code seems not optimize about this). Maybe we can
...
i := 0
for e.VisibilityBitmap {
for c := 0x80; ... {
ret[i] = ...
i++
if i >= e.ColumnCount { return }
}
}
...
Welcome to find different code
| // VisibilityMap returns a map: column index -> visiblity. | ||
| // Invisible column was introduced in MySQL 8.0.23 | ||
| // nil is returned if not available. | ||
| func (e *TableMapEvent) VisibilityMap() map[int]bool { |
There was a problem hiding this comment.
As for testing, I think maybe you can capture/construct some VisibilityBitmap bytes and test the result of TableMapEvent.VisibilityMap is expected.
There was a problem hiding this comment.
@lance6716
Sure. I think I should create a separate function. Just as TestTableMapOptMetaPrimaryKey is defined solely for primary key type meta data. At first, I thought about squeezing into TestTableMapOptMetaNames or TestTableMapHelperMaps, but it's too packed and I saw no room for any addition. Your advice would be help me a lot. 😀
Changes: - Refactpred `UnsignedMap` - Refactored `VisibilityMap` Suggested by: go-mysql-org#813 (comment)
Changes: - Refactpred `UnsignedMap` - Refactored `VisibilityMap` Suggested by: go-mysql-org#813 (comment)
20bf956 to
6260982
Compare
Changes: - Added data for MySQL 8.0 only (Only MySQL 8.0.23+ supports invisible columns)
|
I added test case for 8.0 only, because the keyword |
|
ptal @atercattus |
|
But on a second thought, I would like to add case 2 where invisible columns do not exist at all! This case will be applicable to the rest of vendors and versions too; MySQL 5.7, MariaDB 10.4 and MairaDB 10.5. |
Changes: - Add test case 2 where invisible columns does not exists at all
|
lgtm now. let's wait @atercattus |
|
@dongwook-chan seems atercattus is a bit busy. Do you want me to merge it or you can wait a bit longer ? |
|
@lance6716 No need to wait any longer! |
I was implementing optional_metadata field in table_map_event for python-mysql-replication.
And came across this repo and found that metadata type COLUMN_VISIBILITY isn't implemented.
Changes
TableMapEvent.VisibilityBitmapVisibilityBitmapis a bitmap where each bit represents the visibility of a corresponding column in a table.TableMapEvent.VisibilityMapVisibilityMaplists boolean values of which is true if column of the same index is NOT an invisible column.Examples
You can check the visibility of a column by its table by executing
DESCRIBEcommand.