Skip to content

Commit

Permalink
infoschema: set right columns in infoschema by differ type (#7463)
Browse files Browse the repository at this point in the history
  • Loading branch information
lysu authored and ngaut committed Aug 24, 2018
1 parent 1fa5669 commit db873d6
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 24 deletions.
2 changes: 1 addition & 1 deletion expression/builtin_time.go
Original file line number Diff line number Diff line change
Expand Up @@ -5410,7 +5410,7 @@ func (b *builtinLastDaySig) evalTime(row chunk.Row) (types.Time, bool, error) {
// getExpressionFsp calculates the fsp from given expression.
func getExpressionFsp(ctx sessionctx.Context, expression Expression) (int, error) {
constExp, isConstant := expression.(*Constant)
if isConstant && types.IsString(expression.GetType()) && !isTemporalColumn(expression) {
if isConstant && types.IsString(expression.GetType().Tp) && !isTemporalColumn(expression) {
str, isNil, err := constExp.EvalString(ctx, chunk.Row{})
if isNil || err != nil {
return 0, errors.Trace(err)
Expand Down
45 changes: 29 additions & 16 deletions infoschema/tables.go
Original file line number Diff line number Diff line change
Expand Up @@ -792,8 +792,12 @@ func dataForColumns(ctx sessionctx.Context, schemas []*model.DBInfo) [][]types.D
func dataForColumnsInTable(schema *model.DBInfo, tbl *model.TableInfo) [][]types.Datum {
var rows [][]types.Datum
for i, col := range tbl.Columns {
var charMaxLen, charOctLen, numericPrecision, numericScale, datetimePrecision interface{}
colLen, decimal := col.Flen, col.Decimal
defaultFlen, defaultDecimal := mysql.GetDefaultFieldLengthAndDecimal(col.Tp)
if decimal == types.UnspecifiedLength {
decimal = defaultDecimal
}
if colLen == types.UnspecifiedLength {
colLen = defaultFlen
}
Expand All @@ -808,6 +812,8 @@ func dataForColumnsInTable(schema *model.DBInfo, tbl *model.TableInfo) [][]types
if len(col.Elems) != 0 {
colLen += (len(col.Elems) - 1)
}
charMaxLen = colLen
charOctLen = colLen
} else if col.Tp == mysql.TypeEnum {
// Example: In MySQL enum('a', 'ab', 'cdef') has length 4, because
// the longest string in the enum is 'cdef'
Expand All @@ -818,9 +824,16 @@ func dataForColumnsInTable(schema *model.DBInfo, tbl *model.TableInfo) [][]types
colLen = len(ele)
}
}
}
if decimal == types.UnspecifiedLength {
decimal = defaultDecimal
charMaxLen = colLen
charOctLen = colLen
} else if types.IsString(col.Tp) {
charMaxLen = colLen
charOctLen = colLen
} else if types.IsTypeFractionable(col.Tp) {
datetimePrecision = decimal
} else if types.IsTypeNumeric(col.Tp) {
numericPrecision = colLen
numericScale = decimal
}
columnType := col.FieldType.InfoSchemaStr()
columnDesc := table.NewColDesc(table.ToColumn(col))
Expand All @@ -837,19 +850,19 @@ func dataForColumnsInTable(schema *model.DBInfo, tbl *model.TableInfo) [][]types
columnDefault, // COLUMN_DEFAULT
columnDesc.Null, // IS_NULLABLE
types.TypeToStr(col.Tp, col.Charset), // DATA_TYPE
colLen, // CHARACTER_MAXIMUM_LENGTH
colLen, // CHARACTER_OCTET_LENGTH
decimal, // NUMERIC_PRECISION
0, // NUMERIC_SCALE
0, // DATETIME_PRECISION
col.Charset, // CHARACTER_SET_NAME
col.Collate, // COLLATION_NAME
columnType, // COLUMN_TYPE
columnDesc.Key, // COLUMN_KEY
columnDesc.Extra, // EXTRA
"select,insert,update,references", // PRIVILEGES
columnDesc.Comment, // COLUMN_COMMENT
col.GeneratedExprString, // GENERATION_EXPRESSION
charMaxLen, // CHARACTER_MAXIMUM_LENGTH
charOctLen, // CHARACTER_OCTET_LENGTH
numericPrecision, // NUMERIC_PRECISION
numericScale, // NUMERIC_SCALE
datetimePrecision, // DATETIME_PRECISION
col.Charset, // CHARACTER_SET_NAME
col.Collate, // COLLATION_NAME
columnType, // COLUMN_TYPE
columnDesc.Key, // COLUMN_KEY
columnDesc.Extra, // EXTRA
"select,insert,update,references", // PRIVILEGES
columnDesc.Comment, // COLUMN_COMMENT
col.GeneratedExprString, // GENERATION_EXPRESSION
)
// In mysql, 'character_set_name' and 'collation_name' are setted to null when column type is non-varchar or non-blob in information_schema.
if col.Tp != mysql.TypeVarchar && col.Tp != mysql.TypeBlob {
Expand Down
26 changes: 26 additions & 0 deletions infoschema/tables_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,32 @@ import (
"github.com/pingcap/tidb/util/testleak"
)

func (s *testSuite) TestInfoschemaFielValue(c *C) {
testleak.BeforeTest()
defer testleak.AfterTest(c)()
store, err := mockstore.NewMockTikvStore()
c.Assert(err, IsNil)
defer store.Close()
session.SetStatsLease(0)
do, err := session.BootstrapSession(store)
c.Assert(err, IsNil)
defer do.Close()

tk := testkit.NewTestKit(c, store)
tk.MustExec("use test")
tk.MustExec("drop table if exists numschema, timeschema")
tk.MustExec("create table numschema(i int(2), f float(4,2), d decimal(4,3))")
tk.MustExec("create table timeschema(d date, dt datetime(3), ts timestamp(3), t time(4), y year(4))")
tk.MustExec("create table strschema(c char(3), c2 varchar(3), b blob(3), t text(3))")

tk.MustQuery("select CHARACTER_MAXIMUM_LENGTH,CHARACTER_OCTET_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,DATETIME_PRECISION from information_schema.COLUMNS where table_name='numschema'").
Check(testkit.Rows("<nil> <nil> 2 0 <nil>", "<nil> <nil> 4 2 <nil>", "<nil> <nil> 4 3 <nil>")) // FIXME: for mysql first one will be "<nil> <nil> 10 0 <nil>"
tk.MustQuery("select CHARACTER_MAXIMUM_LENGTH,CHARACTER_OCTET_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,DATETIME_PRECISION from information_schema.COLUMNS where table_name='timeschema'").
Check(testkit.Rows("<nil> <nil> <nil> <nil> <nil>", "<nil> <nil> <nil> <nil> 3", "<nil> <nil> <nil> <nil> 3", "<nil> <nil> <nil> <nil> 4", "<nil> <nil> <nil> <nil> <nil>"))
tk.MustQuery("select CHARACTER_MAXIMUM_LENGTH,CHARACTER_OCTET_LENGTH,NUMERIC_PRECISION,NUMERIC_SCALE,DATETIME_PRECISION from information_schema.COLUMNS where table_name='strschema'").
Check(testkit.Rows("3 3 <nil> <nil> <nil>", "3 3 <nil> <nil> <nil>", "3 3 <nil> <nil> <nil>", "3 3 <nil> <nil> <nil>")) // FIXME: for mysql last two will be "255 255 <nil> <nil> <nil>", "255 255 <nil> <nil> <nil>"
}

func (s *testSuite) TestDataForTableRowsCountField(c *C) {
testleak.BeforeTest()
defer testleak.AfterTest(c)()
Expand Down
19 changes: 12 additions & 7 deletions types/etc.go
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,14 @@ func IsTypeTime(tp byte) bool {
return tp == mysql.TypeDatetime || tp == mysql.TypeDate || tp == mysql.TypeTimestamp
}

// IsTypeFloat returns a boolean indicating whether the tp is floating-point type.
func IsTypeFloat(tp byte) bool {
return tp == mysql.TypeFloat || tp == mysql.TypeDouble
// IsTypeNumeric returns a boolean indicating whether the tp is numeric type.
func IsTypeNumeric(tp byte) bool {
switch tp {
case mysql.TypeBit, mysql.TypeTiny, mysql.TypeInt24, mysql.TypeLong, mysql.TypeLonglong, mysql.TypeNewDecimal,
mysql.TypeDecimal, mysql.TypeFloat, mysql.TypeDouble, mysql.TypeShort:
return true
}
return false
}

// IsTemporalWithDate returns a boolean indicating
Expand All @@ -87,7 +92,7 @@ func IsTemporalWithDate(tp byte) bool {
// IsBinaryStr returns a boolean indicating
// whether the field type is a binary string type.
func IsBinaryStr(ft *FieldType) bool {
if ft.Collate == charset.CollationBin && IsString(ft) {
if ft.Collate == charset.CollationBin && IsString(ft.Tp) {
return true
}
return false
Expand All @@ -96,16 +101,16 @@ func IsBinaryStr(ft *FieldType) bool {
// IsNonBinaryStr returns a boolean indicating
// whether the field type is a non-binary string type.
func IsNonBinaryStr(ft *FieldType) bool {
if ft.Collate != charset.CollationBin && IsString(ft) {
if ft.Collate != charset.CollationBin && IsString(ft.Tp) {
return true
}
return false
}

// IsString returns a boolean indicating
// whether the field type is a string type.
func IsString(ft *FieldType) bool {
return IsTypeChar(ft.Tp) || IsTypeBlob(ft.Tp) || IsTypeVarchar(ft.Tp) || IsTypeUnspecified(ft.Tp)
func IsString(tp byte) bool {
return IsTypeChar(tp) || IsTypeBlob(tp) || IsTypeVarchar(tp) || IsTypeUnspecified(tp)
}

var type2Str = map[byte]string{
Expand Down

0 comments on commit db873d6

Please sign in to comment.