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
plan, util/admin: fix admin check table error when a column of index is virtual generated #6817
Conversation
@crazycs520 Please sign the CLA. |
model/model.go
Outdated
@@ -17,6 +17,7 @@ import ( | |||
"strings" | |||
"time" | |||
|
|||
"fmt" |
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.
Move the fmt
into the upper group.
model/model.go
Outdated
@@ -493,3 +494,8 @@ func collationToProto(c string) int32 { | |||
// For the data created when we didn't enforce utf8_bin collation in create table. | |||
return int32(mysql.DefaultCollationID) | |||
} | |||
|
|||
// GetTableColumnID get a ID of a column with table ID |
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/get/gets/
plan/planbuilder.go
Outdated
p := &CheckTable{Tables: as.Tables} | ||
p.GenExprs = make(map[string]expression.Expression, 0) | ||
|
||
mockTablePlan := LogicalTableDual{}.init(b.ctx) |
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 use LogicalTableDual
?
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.
I mock from buildInsert()
LogicalTableDual
is use to b.rewrite(column.GeneratedExpr, mockTablePlan, nil, true)
I wanna directly use CheckTable
instead of LogicalTableDual
, but it seem not fit
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.
So what's the problem with using CheckTable?
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.
CheckTable
don't implement LogicalPlan
, expr, _, err := b.rewrite
need a LogicalPlan
@@ -493,3 +494,8 @@ func collationToProto(c string) int32 { | |||
// For the data created when we didn't enforce utf8_bin collation in create table. | |||
return int32(mysql.DefaultCollationID) | |||
} | |||
|
|||
// GetTableColumnID gets a ID of a column with table ID | |||
func GetTableColumnID(tableInfo *TableInfo, col *ColumnInfo) string { |
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 this function is only used in buildAdminCheckTable
, you can put it to planbuilder.go
and update its name as getTableColumnID
.
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.
this function also call on util/admin/admin.go
util/admin/admin.go
Outdated
rowMap[col.ID] = val | ||
} | ||
} | ||
if 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.
this check can be removed.
util/admin/admin.go
Outdated
@@ -490,12 +491,30 @@ func rowWithCols(sessCtx sessionctx.Context, txn kv.Retriever, t table.Table, h | |||
} | |||
continue | |||
} | |||
if col.IsGenerated() && col.GeneratedStored == false { | |||
genFlag = true | |||
break |
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 break here? If there are handle column after this column, the check would fail because it did set the handle as line 486 do.
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.
Add some comments here. Why break?
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.
I have remove break.
@crazycs520 Please address comments. |
util/admin/admin.go
Outdated
@@ -244,13 +245,13 @@ func ScanIndexData(sc *stmtctx.StatementContext, txn kv.Transaction, kvIndex tab | |||
// CompareIndexData compares index data one by one. | |||
// It returns nil if the data from the index is equal to the data from the table columns, | |||
// otherwise it returns an error with a different set of records. | |||
func CompareIndexData(sessCtx sessionctx.Context, txn kv.Transaction, t table.Table, idx table.Index) error { | |||
err := checkIndexAndRecord(sessCtx, txn, t, idx) | |||
func CompareIndexData(sessCtx sessionctx.Context, txn kv.Transaction, t table.Table, idx table.Index, genExprs map[string]expression.Expression) 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.
Add some comment to genExprs param.
plan/planbuilder.go
Outdated
schema := expression.TableInfo2SchemaWithDBName(tbl.Schema, tableInfo) | ||
table, ok := b.is.TableByID(tableInfo.ID) | ||
if !ok { | ||
b.err = errors.Errorf("Can't get table %s.", tableInfo.Name.O) |
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.
modify to b.err = infoschema.ErrTableNotExists.GenByArgs(....)
plan/planbuilder.go
Outdated
@@ -494,6 +493,50 @@ func (b *planBuilder) buildAdmin(as *ast.AdminStmt) Plan { | |||
return ret | |||
} | |||
|
|||
func (b *planBuilder) buildAdminCheckTable(as *ast.AdminStmt) Plan { | |||
p := &CheckTable{Tables: as.Tables} | |||
p.GenExprs = make(map[string]expression.Expression, 0) |
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[string]expression.Expression)
is ok.
util/admin/admin.go
Outdated
@@ -539,10 +558,21 @@ func iterRecords(sessCtx sessionctx.Context, retriever kv.Retriever, t table.Tab | |||
|
|||
log.Debugf("startKey:%q, key:%q, value:%q", startKey, it.Key(), it.Value()) | |||
|
|||
genFlag := false |
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/genFlag/genColFlag/g
util/admin/admin.go
Outdated
colTps[col.ID] = &col.FieldType | ||
} | ||
row, err := tablecodec.DecodeRow(value, colTps, sessCtx.GetSessionVars().GetTimeZone()) | ||
if genFlag { |
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.
Add some comments.
/run-all-tests |
executor/executor.go
Outdated
@@ -349,6 +349,8 @@ type CheckTableExec struct { | |||
tables []*ast.TableName | |||
done bool | |||
is infoschema.InfoSchema | |||
|
|||
GenExprs map[string]expression.Expression |
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.
I think we don't need to export this variable.
plan/planbuilder.go
Outdated
@@ -495,6 +494,50 @@ func (b *planBuilder) buildAdmin(as *ast.AdminStmt) Plan { | |||
return ret | |||
} | |||
|
|||
func (b *planBuilder) buildAdminCheckTable(as *ast.AdminStmt) Plan { |
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.
Change the type of return value from Plan
to *CheckTable
would be better.
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
@@ -56,6 +56,8 @@ type CheckTable struct { | |||
baseSchemaProducer | |||
|
|||
Tables []*ast.TableName | |||
|
|||
GenExprs map[string]expression.Expression |
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.
What about map[int]expression.Expression
where the map key is ColumnInfo.ID
.
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.
There maybe have multiple tables, only use ColumnInfo.ID
may leads to conflict in same ColumnInfo.ID
but in different 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.
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.
reset LGTM
executor/admin_test.go
Outdated
@@ -462,6 +462,11 @@ func (s *testSuite) TestAdminCheckTable(c *C) { | |||
} | |||
tk.MustExec(`admin check table test;`) | |||
|
|||
//test index in virtual generated column | |||
tk.MustExec(`drop table if exists test`) |
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 /test/Test
schema := expression.TableInfo2SchemaWithDBName(b.ctx, tbl.Schema, tableInfo) | ||
table, ok := b.is.TableByID(tableInfo.ID) | ||
if !ok { | ||
return nil, infoschema.ErrTableNotExists.GenByArgs(tbl.DBInfo.Name.O, tableInfo.Name.O) |
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/ tbl.DBInfo.Name.O
/ tbl.DBInfo.Name.L
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.
I think the original is better. here is for log, not for compare.
util/admin/admin.go
Outdated
@@ -558,12 +562,34 @@ func rowWithCols(sessCtx sessionctx.Context, txn kv.Retriever, t table.Table, h | |||
} | |||
continue | |||
} | |||
// if have virtual generate column , decode all columns. |
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 / if
/If
/run-all-tests |
/run-unit-test |
What have you changed? (mandatory)
admin check table
will check the Integrity and consistency of index and record.But how to excute
admin check table
read value of index key and record key from tikv, decode , compare the value of the Index and the corresponding column.
Problem
when a column of index is virtual generated , decode the record value will get NULL of the virtual generated column , because the virtual generated column have not stored , then compare will be not consistent.
How i fix it
after decode the record value, before compare , we have to calculate the value of virtual generated column.
Test SQL:
What are the type of the changes (mandatory)?
How has this PR been tested (mandatory)?