func (d *ddl) setCharsetCollationFlenDecimal(tp *types.FieldType) { if len(tp.Charset) == 0 { switch tp.Tp { case mysql.TypeString, mysql.TypeVarchar, mysql.TypeVarString, mysql.TypeBlob, mysql.TypeTinyBlob, mysql.TypeMediumBlob, mysql.TypeLongBlob: tp.Charset, tp.Collate = getDefaultCharsetAndCollate() default: tp.Charset = charset.CharsetBin tp.Collate = charset.CharsetBin } } // If flen is not assigned, assigned it by type. if tp.Flen == types.UnspecifiedLength { tp.Flen = mysql.GetDefaultFieldLength(tp.Tp) } if tp.Decimal == types.UnspecifiedLength { tp.Decimal = mysql.GetDefaultDecimal(tp.Tp) } }
// columnDefToCol converts ColumnDef to Col and TableConstraints. func columnDefToCol(ctx context.Context, offset int, colDef *ast.ColumnDef) (*table.Column, []*ast.Constraint, error) { constraints := []*ast.Constraint{} col := &table.Column{ ColumnInfo: model.ColumnInfo{ Offset: offset, Name: colDef.Name.Name, FieldType: *colDef.Tp, }, } // Check and set TimestampFlag and OnUpdateNowFlag. if col.Tp == mysql.TypeTimestamp { col.Flag |= mysql.TimestampFlag col.Flag |= mysql.OnUpdateNowFlag col.Flag |= mysql.NotNullFlag } // If flen is not assigned, assigned it by type. if col.Flen == types.UnspecifiedLength { col.Flen = mysql.GetDefaultFieldLength(col.Tp) } if col.Decimal == types.UnspecifiedLength { col.Decimal = mysql.GetDefaultDecimal(col.Tp) } setOnUpdateNow := false hasDefaultValue := false if colDef.Options != nil { keys := []*ast.IndexColName{ { Column: colDef.Name, Length: colDef.Tp.Flen, }, } for _, v := range colDef.Options { switch v.Tp { case ast.ColumnOptionNotNull: col.Flag |= mysql.NotNullFlag case ast.ColumnOptionNull: col.Flag &= ^uint(mysql.NotNullFlag) removeOnUpdateNowFlag(col) case ast.ColumnOptionAutoIncrement: col.Flag |= mysql.AutoIncrementFlag case ast.ColumnOptionPrimaryKey: constraint := &ast.Constraint{Tp: ast.ConstraintPrimaryKey, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.PriKeyFlag case ast.ColumnOptionUniq: constraint := &ast.Constraint{Tp: ast.ConstraintUniq, Name: colDef.Name.Name.O, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.UniqueKeyFlag case ast.ColumnOptionIndex: constraint := &ast.Constraint{Tp: ast.ConstraintIndex, Name: colDef.Name.Name.O, Keys: keys} constraints = append(constraints, constraint) case ast.ColumnOptionUniqIndex: constraint := &ast.Constraint{Tp: ast.ConstraintUniqIndex, Name: colDef.Name.Name.O, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.UniqueKeyFlag case ast.ColumnOptionKey: constraint := &ast.Constraint{Tp: ast.ConstraintKey, Name: colDef.Name.Name.O, Keys: keys} constraints = append(constraints, constraint) case ast.ColumnOptionUniqKey: constraint := &ast.Constraint{Tp: ast.ConstraintUniqKey, Name: colDef.Name.Name.O, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.UniqueKeyFlag case ast.ColumnOptionDefaultValue: value, err := getDefaultValue(ctx, v, colDef.Tp.Tp, colDef.Tp.Decimal) if err != nil { return nil, nil, ErrColumnBadNull.Gen("invalid default value - %s", err) } col.DefaultValue = value hasDefaultValue = true removeOnUpdateNowFlag(col) case ast.ColumnOptionOnUpdate: if !evaluator.IsCurrentTimeExpr(v.Expr) { return nil, nil, ErrInvalidOnUpdate.Gen("invalid ON UPDATE for - %s", col.Name) } col.Flag |= mysql.OnUpdateNowFlag setOnUpdateNow = true case ast.ColumnOptionComment: value, err := evaluator.Eval(ctx, v.Expr) if err != nil { return nil, nil, errors.Trace(err) } col.Comment, err = value.ToString() if err != nil { return nil, nil, errors.Trace(err) } case ast.ColumnOptionFulltext: // Do nothing. } } } setTimestampDefaultValue(col, hasDefaultValue, setOnUpdateNow) // Set `NoDefaultValueFlag` if this field doesn't have a default value and // it is `not null` and not an `AUTO_INCREMENT` field or `TIMESTAMP` field. setNoDefaultValueFlag(col, hasDefaultValue) err := checkDefaultValue(col, hasDefaultValue) if err != nil { return nil, nil, errors.Trace(err) } if col.Charset == charset.CharsetBin { col.Flag |= mysql.BinaryFlag } return col, constraints, nil }
// ColumnDefToCol converts ColumnDef to Col and TableConstraints. func ColumnDefToCol(offset int, colDef *ColumnDef) (*column.Col, []*TableConstraint, error) { constraints := []*TableConstraint{} col := &column.Col{ ColumnInfo: model.ColumnInfo{ Offset: offset, Name: model.NewCIStr(colDef.Name), FieldType: *colDef.Tp, }, } // Check and set TimestampFlag and OnUpdateNowFlag. if col.Tp == mysql.TypeTimestamp { col.Flag |= mysql.TimestampFlag col.Flag |= mysql.OnUpdateNowFlag col.Flag |= mysql.NotNullFlag } // If flen is not assigned, assigned it by type. if col.Flen == types.UnspecifiedLength { col.Flen = mysql.GetDefaultFieldLength(col.Tp) } if col.Decimal == types.UnspecifiedLength { col.Decimal = mysql.GetDefaultDecimal(col.Tp) } setOnUpdateNow := false hasDefaultValue := false if colDef.Constraints != nil { keys := []*IndexColName{ { colDef.Name, colDef.Tp.Flen, }, } for _, v := range colDef.Constraints { switch v.Tp { case ConstrNotNull: col.Flag |= mysql.NotNullFlag case ConstrNull: col.Flag &= ^uint(mysql.NotNullFlag) removeOnUpdateNowFlag(col) case ConstrAutoIncrement: col.Flag |= mysql.AutoIncrementFlag case ConstrPrimaryKey: constraint := &TableConstraint{Tp: ConstrPrimaryKey, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.PriKeyFlag case ConstrUniq: constraint := &TableConstraint{Tp: ConstrUniq, ConstrName: colDef.Name, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.UniqueKeyFlag case ConstrIndex: constraint := &TableConstraint{Tp: ConstrIndex, ConstrName: colDef.Name, Keys: keys} constraints = append(constraints, constraint) case ConstrUniqIndex: constraint := &TableConstraint{Tp: ConstrUniqIndex, ConstrName: colDef.Name, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.UniqueKeyFlag case ConstrKey: constraint := &TableConstraint{Tp: ConstrKey, ConstrName: colDef.Name, Keys: keys} constraints = append(constraints, constraint) case ConstrUniqKey: constraint := &TableConstraint{Tp: ConstrUniqKey, ConstrName: colDef.Name, Keys: keys} constraints = append(constraints, constraint) col.Flag |= mysql.UniqueKeyFlag case ConstrDefaultValue: value, err := getDefaultValue(v, colDef.Tp.Tp, colDef.Tp.Decimal) if err != nil { return nil, nil, errors.Errorf("invalid default value - %s", errors.Trace(err)) } col.DefaultValue = value hasDefaultValue = true removeOnUpdateNowFlag(col) case ConstrOnUpdate: if !expression.IsCurrentTimeExpr(v.Evalue) { return nil, nil, errors.Errorf("invalid ON UPDATE for - %s", col.Name) } col.Flag |= mysql.OnUpdateNowFlag setOnUpdateNow = true case ConstrFulltext: // Do nothing. case ConstrComment: // Do nothing. } } } setTimestampDefaultValue(col, hasDefaultValue, setOnUpdateNow) // Set `NoDefaultValueFlag` if this field doesn't have a default value and // it is `not null` and not an `AUTO_INCREMENT` field or `TIMESTAMP` field. setNoDefaultValueFlag(col, hasDefaultValue) err := checkDefaultValue(col, hasDefaultValue) if err != nil { return nil, nil, errors.Trace(err) } if col.Charset == charset.CharsetBin { col.Flag |= mysql.BinaryFlag } return col, constraints, nil }