diff --git a/field/result_field.go b/field/result_field.go index 9e3803b01a..c6847bc3db 100644 --- a/field/result_field.go +++ b/field/result_field.go @@ -24,7 +24,6 @@ import ( "github.com/juju/errors" "github.com/pingcap/tidb/column" mysql "github.com/pingcap/tidb/mysqldef" - "github.com/pingcap/tidb/util/types" ) const ( @@ -89,14 +88,6 @@ func ColToResultField(col *column.Col, tableName string) *ResultField { TableName: tableName, OrgTableName: tableName, } - - if rf.Col.Flen == types.UnspecifiedLength { - rf.Col.Flen = 0 - } - if rf.Col.Decimal == types.UnspecifiedLength { - rf.Col.Decimal = 0 - } - // Keep things compatible for old clients. // Refer to mysql-server/sql/protocol.cc send_result_set_metadata() if rf.Tp == mysql.TypeVarchar { diff --git a/mysqldef/util.go b/mysqldef/util.go index da8c9c7927..11f08c03a3 100644 --- a/mysqldef/util.go +++ b/mysqldef/util.go @@ -17,6 +17,7 @@ package mysqldef // Call this when no Flen assigned in ddl. // or column value is calculated from an expression. // For example: "select count(*) from t;", the column type is int64 and Flen in ResultField will be 21. +// See: https://dev.mysql.com/doc/refman/5.7/en/storage-requirements.html func GetDefaultFieldLength(tp byte) int { switch tp { case TypeTiny: @@ -29,8 +30,25 @@ func GetDefaultFieldLength(tp byte) int { return 11 case TypeLonglong: return 21 + case TypeDecimal: + // See: https://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html + return 10 + case TypeBit, TypeBlob: + return -1 default: //TODO: add more types - return 0 + return -1 + } +} + +// GetDefaultDecimal returns the default decimal length for column. +func GetDefaultDecimal(tp byte) int { + switch tp { + case TypeDecimal: + // See: https://dev.mysql.com/doc/refman/5.7/en/fixed-point-types.html + return 0 + default: + //TODO: add more types + return -1 } } diff --git a/mysqldef/util_test.go b/mysqldef/util_test.go index 1baff0c452..e2e98a9f9d 100644 --- a/mysqldef/util_test.go +++ b/mysqldef/util_test.go @@ -25,7 +25,9 @@ func TestGetFieldLength(t *testing.T) { {TypeInt24, 9}, {TypeLong, 11}, {TypeLonglong, 21}, - {TypeNull, 0}, + {TypeBit, -1}, + {TypeBlob, -1}, + {TypeNull, -1}, } for _, test := range tbl { diff --git a/parser/coldef/col_def.go b/parser/coldef/col_def.go index 041afb6832..8010c08dec 100644 --- a/parser/coldef/col_def.go +++ b/parser/coldef/col_def.go @@ -181,9 +181,12 @@ func ColumnDefToCol(offset int, colDef *ColumnDef) (*column.Col, []*TableConstra } // If flen is not assigned, assigned it by type. - if col.Flen == 0 { + 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 diff --git a/plan/plans/info.go b/plan/plans/info.go index 2779dfbe1e..3a2b214314 100644 --- a/plan/plans/info.go +++ b/plan/plans/info.go @@ -361,8 +361,14 @@ func (isp *InfoSchemaPlan) fetchColumns(schemas []*model.DBInfo) { if decimal == types.UnspecifiedLength { decimal = 0 } - dataType := types.TypeToStr(col.Tp, col.Charset == charset.CharsetBin) - columnType := fmt.Sprintf("%s(%d)", dataType, colLen) + columnType := types.TypeToStr(col.Tp, col.Charset == charset.CharsetBin) + if col.Decimal == types.UnspecifiedLength { + if colLen != types.UnspecifiedLength { + columnType = fmt.Sprintf("%s(%d)", columnType, colLen) + } + } else { + columnType = fmt.Sprintf("%s(%d, %d)", columnType, colLen, col.Decimal) + } columnDesc := column.NewColDesc(&column.Col{ColumnInfo: *col}) var columnDefault interface{} if columnDesc.DefaultValue != nil { diff --git a/tidb-server/server/conn.go b/tidb-server/server/conn.go index 26f290b4bd..5f19f589fb 100644 --- a/tidb-server/server/conn.go +++ b/tidb-server/server/conn.go @@ -433,6 +433,7 @@ func (cc *clientConn) writeResultset(rs ResultSet, binary bool) error { var rowData []byte rowData, err = dumpRowValuesBinary(cc.alloc, columns, row) if err != nil { + fmt.Println("[conn]", err) return errors.Trace(err) } data = append(data, rowData...) diff --git a/tidb-server/server/driver_tidb.go b/tidb-server/server/driver_tidb.go index 1ea32908fa..f536ca92ec 100644 --- a/tidb-server/server/driver_tidb.go +++ b/tidb-server/server/driver_tidb.go @@ -272,8 +272,16 @@ func convertColumnInfo(fld *field.ResultField) (ci *ColumnInfo) { ci.Schema = fld.DBName ci.Flag = uint16(fld.Flag) ci.Charset = uint16(mysql.CharsetIDs[fld.Charset]) - ci.ColumnLength = uint32(fld.Flen) - ci.Decimal = uint8(fld.Decimal) + if fld.Flen == -1 { + ci.ColumnLength = 0 + } else { + ci.ColumnLength = uint32(fld.Flen) + } + if fld.Decimal == -1 { + ci.Decimal = 0 + } else { + ci.Decimal = uint8(fld.Decimal) + } ci.Type = uint8(fld.Tp) return } diff --git a/tidb_test.go b/tidb_test.go index b14b5fdbad..71e957420c 100644 --- a/tidb_test.go +++ b/tidb_test.go @@ -888,7 +888,7 @@ func (s *testSessionSuite) TestShow(c *C) { rows, err := r.Rows(-1, 0) c.Assert(err, IsNil) c.Assert(rows, HasLen, 1) - match(c, rows[0], "c", "int", "YES", "", nil, "") + match(c, rows[0], "c", "int(11)", "YES", "", nil, "") r = mustExecSQL(c, se, "show collation where Charset = 'utf8' and Collation = 'utf8_bin'") row, err = r.FirstRow() diff --git a/util/types/etc.go b/util/types/etc.go index 7387e25515..b2e7cde4da 100644 --- a/util/types/etc.go +++ b/util/types/etc.go @@ -89,22 +89,22 @@ func TypeStr(tp byte) (r string) { func TypeToStr(tp byte, binary bool) string { switch tp { case mysql.TypeBlob: - if binary { + if !binary { return "text" } return "blob" case mysql.TypeLongBlob: - if binary { + if !binary { return "longtext" } return "longblob" case mysql.TypeTinyBlob: - if binary { + if !binary { return "tinytext" } return "tinyblob" case mysql.TypeMediumBlob: - if binary { + if !binary { return "mediumtext" } return "mediumblob" diff --git a/util/types/etc_test.go b/util/types/etc_test.go index 6212535605..b1af52f00d 100644 --- a/util/types/etc_test.go +++ b/util/types/etc_test.go @@ -68,17 +68,17 @@ func (s *testTypeEtcSuite) TestTypeToStr(c *C) { testTypeStr(c, mysql.TypeYear, "year") testTypeStr(c, 0xdd, "") - testTypeToStr(c, mysql.TypeBlob, true, "text") - testTypeToStr(c, mysql.TypeLongBlob, true, "longtext") - testTypeToStr(c, mysql.TypeTinyBlob, true, "tinytext") - testTypeToStr(c, mysql.TypeMediumBlob, true, "mediumtext") + testTypeToStr(c, mysql.TypeBlob, false, "text") + testTypeToStr(c, mysql.TypeLongBlob, false, "longtext") + testTypeToStr(c, mysql.TypeTinyBlob, false, "tinytext") + testTypeToStr(c, mysql.TypeMediumBlob, false, "mediumtext") testTypeToStr(c, mysql.TypeVarchar, true, "varbinary") testTypeToStr(c, mysql.TypeString, true, "binary") testTypeToStr(c, mysql.TypeTiny, true, "tinyint") - testTypeToStr(c, mysql.TypeBlob, false, "blob") - testTypeToStr(c, mysql.TypeLongBlob, false, "longblob") - testTypeToStr(c, mysql.TypeTinyBlob, false, "tinyblob") - testTypeToStr(c, mysql.TypeMediumBlob, false, "mediumblob") + testTypeToStr(c, mysql.TypeBlob, true, "blob") + testTypeToStr(c, mysql.TypeLongBlob, true, "longblob") + testTypeToStr(c, mysql.TypeTinyBlob, true, "tinyblob") + testTypeToStr(c, mysql.TypeMediumBlob, true, "mediumblob") testTypeToStr(c, mysql.TypeVarchar, false, "varchar") testTypeToStr(c, mysql.TypeString, false, "char") testTypeToStr(c, mysql.TypeShort, true, "smallint")