Skip to content

Commit

Permalink
ddl: export method for needChangeColumns (#47492)
Browse files Browse the repository at this point in the history
ref #46258
  • Loading branch information
GMHDBJD authored Oct 10, 2023
1 parent 80faa9c commit 379ea38
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 34 deletions.
10 changes: 6 additions & 4 deletions ddl/column.go
Original file line number Diff line number Diff line change
Expand Up @@ -385,7 +385,7 @@ func needChangeColumnData(oldCol, newCol *model.ColumnInfo) bool {
// cut to eliminate data reorg change for column type change between decimal.
return oldCol.GetFlen() != newCol.GetFlen() || oldCol.GetDecimal() != newCol.GetDecimal() || toUnsigned != originUnsigned
case mysql.TypeEnum, mysql.TypeSet:
return isElemsChangedToModifyColumn(oldCol.GetElems(), newCol.GetElems())
return IsElemsChangedToModifyColumn(oldCol.GetElems(), newCol.GetElems())
case mysql.TypeTiny, mysql.TypeShort, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong:
return toUnsigned != originUnsigned
case mysql.TypeString:
Expand All @@ -398,7 +398,7 @@ func needChangeColumnData(oldCol, newCol *model.ColumnInfo) bool {
return needTruncationOrToggleSign()
}

if convertBetweenCharAndVarchar(oldCol.GetType(), newCol.GetType()) {
if ConvertBetweenCharAndVarchar(oldCol.GetType(), newCol.GetType()) {
return true
}

Expand All @@ -420,12 +420,14 @@ func needChangeColumnData(oldCol, newCol *model.ColumnInfo) bool {
return true
}

// ConvertBetweenCharAndVarchar check whether column converted between char and varchar
// TODO: it is used for plugins. so change plugin's using and remove it.
func convertBetweenCharAndVarchar(oldCol, newCol byte) bool {
func ConvertBetweenCharAndVarchar(oldCol, newCol byte) bool {
return types.ConvertBetweenCharAndVarchar(oldCol, newCol)
}

func isElemsChangedToModifyColumn(oldElems, newElems []string) bool {
// IsElemsChangedToModifyColumn check elems changed
func IsElemsChangedToModifyColumn(oldElems, newElems []string) bool {
if len(newElems) < len(oldElems) {
return true
}
Expand Down
69 changes: 39 additions & 30 deletions ddl/ddl_api.go
Original file line number Diff line number Diff line change
Expand Up @@ -5271,8 +5271,8 @@ func setColumnComment(ctx sessionctx.Context, col *table.Column, option *ast.Col
return errors.Trace(err)
}

// processColumnOptions is only used in getModifiableColumnJob.
func processColumnOptions(ctx sessionctx.Context, col *table.Column, options []*ast.ColumnOption) error {
// ProcessColumnOptions process column options.
func ProcessColumnOptions(ctx sessionctx.Context, col *table.Column, options []*ast.ColumnOption) error {
var sb strings.Builder
restoreFlags := format.RestoreStringSingleQuotes | format.RestoreKeyWordLowercase | format.RestoreNameBackQuotes |
format.RestoreSpacesAroundBinaryOperation | format.RestoreWithoutSchemaName | format.RestoreWithoutSchemaName
Expand Down Expand Up @@ -5402,6 +5402,39 @@ func checkModifyColumnWithGeneratedColumnsConstraint(allCols []*table.Column, ol
return nil
}

// ProcessColumnCharsetAndCollation process column charset and collation
func ProcessColumnCharsetAndCollation(sctx sessionctx.Context, col *table.Column, newCol *table.Column, meta *model.TableInfo, specNewColumn *ast.ColumnDef, schema *model.DBInfo) error {
var chs, coll string
var err error
// TODO: Remove it when all table versions are greater than or equal to TableInfoVersion1.
// If newCol's charset is empty and the table's version less than TableInfoVersion1,
// we will not modify the charset of the column. This behavior is not compatible with MySQL.
if len(newCol.FieldType.GetCharset()) == 0 && meta.Version < model.TableInfoVersion1 {
chs = col.FieldType.GetCharset()
coll = col.FieldType.GetCollate()
} else {
chs, coll, err = getCharsetAndCollateInColumnDef(sctx.GetSessionVars(), specNewColumn)
if err != nil {
return errors.Trace(err)
}
chs, coll, err = ResolveCharsetCollation(sctx.GetSessionVars(),
ast.CharsetOpt{Chs: chs, Col: coll},
ast.CharsetOpt{Chs: meta.Charset, Col: meta.Collate},
ast.CharsetOpt{Chs: schema.Charset, Col: schema.Collate},
)
chs, coll = OverwriteCollationWithBinaryFlag(sctx.GetSessionVars(), specNewColumn, chs, coll)
if err != nil {
return errors.Trace(err)
}
}

if err = setCharsetCollationFlenDecimal(&newCol.FieldType, newCol.Name.O, chs, coll, sctx.GetSessionVars()); err != nil {
return errors.Trace(err)
}
decodeEnumSetBinaryLiteralToUTF8(&newCol.FieldType, chs)
return nil
}

// GetModifiableColumnJob returns a DDL job of model.ActionModifyColumn.
func GetModifiableColumnJob(
ctx context.Context,
Expand Down Expand Up @@ -5469,36 +5502,12 @@ func GetModifiableColumnJob(
Version: col.Version,
})

var chs, coll string
// TODO: Remove it when all table versions are greater than or equal to TableInfoVersion1.
// If newCol's charset is empty and the table's version less than TableInfoVersion1,
// we will not modify the charset of the column. This behavior is not compatible with MySQL.
if len(newCol.FieldType.GetCharset()) == 0 && t.Meta().Version < model.TableInfoVersion1 {
chs = col.FieldType.GetCharset()
coll = col.FieldType.GetCollate()
} else {
chs, coll, err = getCharsetAndCollateInColumnDef(sctx.GetSessionVars(), specNewColumn)
if err != nil {
return nil, errors.Trace(err)
}
chs, coll, err = ResolveCharsetCollation(sctx.GetSessionVars(),
ast.CharsetOpt{Chs: chs, Col: coll},
ast.CharsetOpt{Chs: t.Meta().Charset, Col: t.Meta().Collate},
ast.CharsetOpt{Chs: schema.Charset, Col: schema.Collate},
)
chs, coll = OverwriteCollationWithBinaryFlag(sctx.GetSessionVars(), specNewColumn, chs, coll)
if err != nil {
return nil, errors.Trace(err)
}
}

if err = setCharsetCollationFlenDecimal(&newCol.FieldType, newCol.Name.O, chs, coll, sctx.GetSessionVars()); err != nil {
return nil, errors.Trace(err)
if err = ProcessColumnCharsetAndCollation(sctx, col, newCol, t.Meta(), specNewColumn, schema); err != nil {
return nil, err
}
decodeEnumSetBinaryLiteralToUTF8(&newCol.FieldType, chs)

if err = checkModifyColumnWithForeignKeyConstraint(is, schema.Name.L, t.Meta(), col.ColumnInfo, newCol.ColumnInfo); err != nil {
return nil, err
return nil, errors.Trace(err)
}

// Copy index related options to the new spec.
Expand All @@ -5509,7 +5518,7 @@ func GetModifiableColumnJob(
// TODO: If user explicitly set NULL, we should throw error ErrPrimaryCantHaveNull.
}

if err = processColumnOptions(sctx, newCol, specNewColumn.Options); err != nil {
if err = ProcessColumnOptions(sctx, newCol, specNewColumn.Options); err != nil {
return nil, errors.Trace(err)
}

Expand Down

0 comments on commit 379ea38

Please sign in to comment.