// GetColDefaultValue gets default value of the column. func GetColDefaultValue(ctx context.Context, col *model.ColumnInfo) (interface{}, bool, error) { // Check no default value flag. if mysql.HasNoDefaultValueFlag(col.Flag) && col.Tp != mysql.TypeEnum { return nil, false, errors.Errorf("Field '%s' doesn't have a default value", col.Name) } // Check and get timestamp/datetime default value. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { if col.DefaultValue == nil { return nil, true, nil } value, err := expression.GetTimeValue(ctx, col.DefaultValue, col.Tp, col.Decimal) if err != nil { return nil, true, errors.Errorf("Field '%s' get default value fail - %s", col.Name, errors.Trace(err)) } return value, true, nil } else if col.Tp == mysql.TypeEnum { // For enum type, if no default value and not null is set, // the default value is the first element of the enum list if col.DefaultValue == nil && mysql.HasNotNullFlag(col.Flag) { return col.FieldType.Elems[0], true, nil } } return col.DefaultValue, true, nil }
// getColDefaultValue gets default value of the column. func getColDefaultValue(col *model.ColumnInfo) (interface{}, bool, error) { // Check no default value flag. if mysql.HasNoDefaultValueFlag(col.Flag) && col.Tp != mysql.TypeEnum { return nil, false, errors.Errorf("Field '%s' doesn't have a default value", col.Name) } // Check and get timestamp/datetime default value. if col.Tp == mysql.TypeEnum { // For enum type, if no default value and not null is set, // the default value is the first element of the enum list if col.DefaultValue == nil && mysql.HasNotNullFlag(col.Flag) { return col.FieldType.Elems[0], true, nil } } return col.DefaultValue, true, nil }
// NewColDesc returns a new ColDesc for a column. func NewColDesc(col *Column) *ColDesc { // TODO: if we have no primary key and a unique index which's columns are all not null // we will set these columns' flag as PriKeyFlag // see https://dev.mysql.com/doc/refman/5.7/en/show-columns.html // create table name := col.Name nullFlag := "YES" if mysql.HasNotNullFlag(col.Flag) { nullFlag = "NO" } keyFlag := "" if mysql.HasPriKeyFlag(col.Flag) { keyFlag = "PRI" } else if mysql.HasUniKeyFlag(col.Flag) { keyFlag = "UNI" } else if mysql.HasMultipleKeyFlag(col.Flag) { keyFlag = "MUL" } var defaultValue interface{} if !mysql.HasNoDefaultValueFlag(col.Flag) { defaultValue = col.DefaultValue } extra := "" if mysql.HasAutoIncrementFlag(col.Flag) { extra = "auto_increment" } else if mysql.HasOnUpdateNowFlag(col.Flag) { extra = "on update CURRENT_TIMESTAMP" } return &ColDesc{ Field: name.O, Type: col.GetTypeDesc(), Collation: col.Collate, Null: nullFlag, Key: keyFlag, DefaultValue: defaultValue, Extra: extra, Privileges: defaultPrivileges, Comment: "", } }
// GetColDefaultValue gets default value of the column. func GetColDefaultValue(ctx context.Context, col *model.ColumnInfo) (types.Datum, bool, error) { // Check no default value flag. if mysql.HasNoDefaultValueFlag(col.Flag) && col.Tp != mysql.TypeEnum { err := errNoDefaultValue.Gen("Field '%s' doesn't have a default value", col.Name) if ctx != nil { sessVars := variable.GetSessionVars(ctx) if !sessVars.StrictSQLMode { // TODO: add warning. return GetZeroValue(col), true, nil } } return types.Datum{}, false, errors.Trace(err) } // Check and get timestamp/datetime default value. if col.Tp == mysql.TypeTimestamp || col.Tp == mysql.TypeDatetime { if col.DefaultValue == nil { return types.Datum{}, true, nil } value, err := evaluator.GetTimeValue(ctx, col.DefaultValue, col.Tp, col.Decimal) if err != nil { return types.Datum{}, true, errGetDefaultFailed.Gen("Field '%s' get default value fail - %s", col.Name, errors.Trace(err)) } return value, true, nil } else if col.Tp == mysql.TypeEnum { // For enum type, if no default value and not null is set, // the default value is the first element of the enum list if col.DefaultValue == nil && mysql.HasNotNullFlag(col.Flag) { return types.NewDatum(col.FieldType.Elems[0]), true, nil } } value, err := CastValue(ctx, types.NewDatum(col.DefaultValue), col) if err != nil { return types.Datum{}, false, errors.Trace(err) } return value, true, nil }
func (e *ShowExec) fetchShowCreateTable() error { tb, err := e.getTable() if err != nil { return errors.Trace(err) } // TODO: let the result more like MySQL. var buf bytes.Buffer buf.WriteString(fmt.Sprintf("CREATE TABLE `%s` (\n", tb.Meta().Name.O)) var pkCol *table.Column for i, col := range tb.Cols() { buf.WriteString(fmt.Sprintf(" `%s` %s", col.Name.O, col.GetTypeDesc())) if mysql.HasAutoIncrementFlag(col.Flag) { buf.WriteString(" NOT NULL AUTO_INCREMENT") } else { if mysql.HasNotNullFlag(col.Flag) { buf.WriteString(" NOT NULL") } if !mysql.HasNoDefaultValueFlag(col.Flag) { switch col.DefaultValue { case nil: buf.WriteString(" DEFAULT NULL") case "CURRENT_TIMESTAMP": buf.WriteString(" DEFAULT CURRENT_TIMESTAMP") default: buf.WriteString(fmt.Sprintf(" DEFAULT '%v'", col.DefaultValue)) } } if mysql.HasOnUpdateNowFlag(col.Flag) { buf.WriteString(" ON UPDATE CURRENT_TIMESTAMP") } } if len(col.Comment) > 0 { buf.WriteString(fmt.Sprintf(" COMMENT '%s'", col.Comment)) } if i != len(tb.Cols())-1 { buf.WriteString(",\n") } if tb.Meta().PKIsHandle && mysql.HasPriKeyFlag(col.Flag) { pkCol = col } } if pkCol != nil { // If PKIsHanle, pk info is not in tb.Indices(). We should handle it here. buf.WriteString(",\n") buf.WriteString(fmt.Sprintf(" PRIMARY KEY (`%s`)", pkCol.Name.O)) } if len(tb.Indices()) > 0 || len(tb.Meta().ForeignKeys) > 0 { buf.WriteString(",\n") } for i, idx := range tb.Indices() { idxInfo := idx.Meta() if idxInfo.Primary { buf.WriteString(" PRIMARY KEY ") } else if idxInfo.Unique { buf.WriteString(fmt.Sprintf(" UNIQUE KEY `%s` ", idxInfo.Name.O)) } else { buf.WriteString(fmt.Sprintf(" KEY `%s` ", idxInfo.Name.O)) } cols := make([]string, 0, len(idxInfo.Columns)) for _, c := range idxInfo.Columns { cols = append(cols, c.Name.O) } buf.WriteString(fmt.Sprintf("(`%s`)", strings.Join(cols, "`,`"))) if i != len(tb.Indices())-1 { buf.WriteString(",\n") } } if len(tb.Indices()) > 0 && len(tb.Meta().ForeignKeys) > 0 { buf.WriteString(",\n") } for _, fk := range tb.Meta().ForeignKeys { if fk.State != model.StatePublic { continue } cols := make([]string, 0, len(fk.Cols)) for _, c := range fk.Cols { cols = append(cols, c.O) } refCols := make([]string, 0, len(fk.RefCols)) for _, c := range fk.Cols { refCols = append(refCols, c.O) } buf.WriteString(fmt.Sprintf(" CONSTRAINT `%s` FOREIGN KEY (`%s`)", fk.Name.O, strings.Join(cols, "`,`"))) buf.WriteString(fmt.Sprintf(" REFERENCES `%s` (`%s`)", fk.RefTable.O, strings.Join(refCols, "`,`"))) if ast.ReferOptionType(fk.OnDelete) != ast.ReferOptionNoOption { buf.WriteString(fmt.Sprintf(" ON DELETE %s", ast.ReferOptionType(fk.OnDelete))) } if ast.ReferOptionType(fk.OnUpdate) != ast.ReferOptionNoOption { buf.WriteString(fmt.Sprintf(" ON UPDATE %s", ast.ReferOptionType(fk.OnUpdate))) } } buf.WriteString("\n") buf.WriteString(") ENGINE=InnoDB") if s := tb.Meta().Charset; len(s) > 0 { buf.WriteString(fmt.Sprintf(" DEFAULT CHARSET=%s", s)) } if tb.Meta().AutoIncID > 0 { buf.WriteString(fmt.Sprintf(" AUTO_INCREMENT=%d", tb.Meta().AutoIncID)) } if len(tb.Meta().Comment) > 0 { buf.WriteString(fmt.Sprintf(" COMMENT='%s'", tb.Meta().Comment)) } data := types.MakeDatums(tb.Meta().Name.O, buf.String()) e.rows = append(e.rows, &Row{Data: data}) return nil }