func (isp *InfoSchemaPlan) doColumns(schemas []*model.DBInfo, iterFunc plan.RowIterFunc) error { for _, schema := range schemas { for _, table := range schema.Tables { for i, col := range table.Columns { colLen := col.Flen if colLen == types.UnspecifiedLength { colLen = mysql.GetDefaultFieldLength(col.Tp) } decimal := col.Decimal if decimal == types.UnspecifiedLength { decimal = 0 } dataType := types.TypeToStr(col.Tp, col.Charset == charset.CharsetBin) columnType := fmt.Sprintf("%s(%d)", dataType, colLen) columnDesc := column.NewColDesc(&column.Col{ColumnInfo: *col}) var columnDefault interface{} if columnDesc.DefaultValue != nil { columnDefault = fmt.Sprintf("%v", columnDesc.DefaultValue) } record := []interface{}{ catalogVal, // TABLE_CATALOG schema.Name.O, // TABLE_SCHEMA table.Name.O, // TABLE_NAME col.Name.O, // COLUMN_NAME i + 1, // ORIGINAL_POSITION columnDefault, // COLUMN_DEFAULT columnDesc.Null, // IS_NULLABLE types.TypeToStr(col.Tp, col.Charset == charset.CharsetBin), // DATA_TYPE colLen, // CHARACTER_MAXIMUM_LENGTH colLen, // CHARACTOR_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 "", // COLUMN_COMMENT } if more, err := iterFunc(0, record); !more || err != nil { return err } } } } return nil }
func (s *ShowPlan) fetchShowColumns(ctx context.Context) error { is := sessionctx.GetDomain(ctx).InfoSchema() dbName := model.NewCIStr(s.DBName) if !is.SchemaExists(dbName) { return errors.Errorf("Can not find DB: %s", dbName) } tbName := model.NewCIStr(s.TableName) tb, err := is.TableByName(dbName, tbName) if err != nil { return errors.Errorf("Can not find table: %s", s.TableName) } cols := tb.Cols() for _, col := range cols { if !s.isColOK(col) { continue } desc := column.NewColDesc(col) // The FULL keyword causes the output to include the column collation and comments, // as well as the privileges you have for each column. row := &plan.Row{} if s.Full { row.Data = []interface{}{ desc.Field, desc.Type, desc.Collation, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, desc.Privileges, desc.Comment, } } else { row.Data = []interface{}{ desc.Field, desc.Type, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, } } s.rows = append(s.rows, row) } return nil }
func (isp *InfoSchemaPlan) fetchColumns(schemas []*model.DBInfo) { for _, schema := range schemas { for _, table := range schema.Tables { for i, col := range table.Columns { colLen := col.Flen if colLen == types.UnspecifiedLength { colLen = mysql.GetDefaultFieldLength(col.Tp) } decimal := col.Decimal if decimal == types.UnspecifiedLength { decimal = 0 } columnType := col.FieldType.CompactStr() columnDesc := column.NewColDesc(&column.Col{ColumnInfo: *col}) var columnDefault interface{} if columnDesc.DefaultValue != nil { columnDefault = fmt.Sprintf("%v", columnDesc.DefaultValue) } record := []interface{}{ catalogVal, // TABLE_CATALOG schema.Name.O, // TABLE_SCHEMA table.Name.O, // TABLE_NAME col.Name.O, // COLUMN_NAME i + 1, // ORIGINAL_POSITION columnDefault, // COLUMN_DEFAULT columnDesc.Null, // IS_NULLABLE types.TypeToStr(col.Tp, col.Charset), // DATA_TYPE colLen, // CHARACTER_MAXIMUM_LENGTH colLen, // CHARACTOR_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 "", // COLUMN_COMMENT } isp.rows = append(isp.rows, &plan.Row{Data: record}) } } } }
func (s *ShowPlan) fetchShowColumns(ctx context.Context) error { tb, err := s.getTable(ctx) if err != nil { return errors.Trace(err) } cols := tb.Cols() for _, col := range cols { if !s.isColOK(col) { continue } desc := column.NewColDesc(col) // The FULL keyword causes the output to include the column collation and comments, // as well as the privileges you have for each column. row := &plan.Row{} if s.Full { row.Data = []interface{}{ desc.Field, desc.Type, desc.Collation, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, desc.Privileges, desc.Comment, } } else { row.Data = []interface{}{ desc.Field, desc.Type, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, } } s.rows = append(s.rows, row) } return nil }
func dataForColumnsInTable(schema *model.DBInfo, table *model.TableInfo) [][]types.Datum { rows := [][]types.Datum{} for i, col := range table.Columns { colLen := col.Flen if colLen == types.UnspecifiedLength { colLen = mysql.GetDefaultFieldLength(col.Tp) } decimal := col.Decimal if decimal == types.UnspecifiedLength { decimal = 0 } columnType := col.FieldType.CompactStr() columnDesc := column.NewColDesc(&column.Col{ColumnInfo: *col}) var columnDefault interface{} if columnDesc.DefaultValue != nil { columnDefault = fmt.Sprintf("%v", columnDesc.DefaultValue) } record := types.MakeDatums( catalogVal, // TABLE_CATALOG schema.Name.O, // TABLE_SCHEMA table.Name.O, // TABLE_NAME col.Name.O, // COLUMN_NAME i+1, // ORIGINAL_POSITION columnDefault, // COLUMN_DEFAULT columnDesc.Null, // IS_NULLABLE types.TypeToStr(col.Tp, col.Charset), // DATA_TYPE colLen, // CHARACTER_MAXIMUM_LENGTH colLen, // CHARACTOR_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 "", // COLUMN_COMMENT ) rows = append(rows, record) } return rows }
func (e *ShowExec) fetchShowColumns() error { tb, err := e.getTable() if err != nil { return errors.Trace(err) } cols := tb.Cols() for _, col := range cols { if e.Column != nil && e.Column.Name.L != col.Name.L { continue } desc := column.NewColDesc(col) // The FULL keyword causes the output to include the column collation and comments, // as well as the privileges you have for each column. row := &Row{} if e.Full { row.Data = types.MakeDatums( desc.Field, desc.Type, desc.Collation, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, desc.Privileges, desc.Comment, ) } else { row.Data = types.MakeDatums( desc.Field, desc.Type, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, ) } e.rows = append(e.rows, row) } return nil }
func (s *ShowPlan) fetchAll(ctx context.Context) error { // TODO split this function switch s.Target { case stmt.ShowEngines: row := &plan.Row{ Data: []interface{}{"InnoDB", "DEFAULT", "Supports transactions, row-level locking, and foreign keys", "YES", "YES", "YES"}, } s.rows = append(s.rows, row) case stmt.ShowDatabases: dbs := sessionctx.GetDomain(ctx).InfoSchema().AllSchemaNames() // TODO: let information_schema be the first database sort.Strings(dbs) for _, d := range dbs { s.rows = append(s.rows, &plan.Row{Data: []interface{}{d}}) } case stmt.ShowTables: is := sessionctx.GetDomain(ctx).InfoSchema() dbName := model.NewCIStr(s.DBName) if !is.SchemaExists(dbName) { return errors.Errorf("Can not find DB: %s", dbName) } // sort for tables var tableNames []string for _, v := range is.SchemaTables(dbName) { tableNames = append(tableNames, v.TableName().L) } sort.Strings(tableNames) for _, v := range tableNames { s.rows = append(s.rows, &plan.Row{Data: []interface{}{v}}) } case stmt.ShowColumns: is := sessionctx.GetDomain(ctx).InfoSchema() dbName := model.NewCIStr(s.DBName) if !is.SchemaExists(dbName) { return errors.Errorf("Can not find DB: %s", dbName) } tbName := model.NewCIStr(s.TableName) tb, err := is.TableByName(dbName, tbName) if err != nil { return errors.Errorf("Can not find table: %s", s.TableName) } cols := tb.Cols() for _, col := range cols { if !s.isColOK(col) { continue } desc := column.NewColDesc(col) // The FULL keyword causes the output to include the column collation and comments, // as well as the privileges you have for each column. row := &plan.Row{} if s.Full { row.Data = []interface{}{ desc.Field, desc.Type, desc.Collation, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, desc.Privileges, desc.Comment, } } else { row.Data = []interface{}{ desc.Field, desc.Type, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, } } s.rows = append(s.rows, row) } case stmt.ShowWarnings: // empty result case stmt.ShowCharset: // See: http://dev.mysql.com/doc/refman/5.7/en/show-character-set.html descs := charset.GetAllCharsets() for _, desc := range descs { row := &plan.Row{ Data: []interface{}{desc.Name, desc.Desc, desc.DefaultCollation, desc.Maxlen}, } s.rows = append(s.rows, row) } case stmt.ShowVariables: sessionVars := variable.GetSessionVars(ctx) for _, v := range variable.SysVars { if s.Pattern != nil { s.Pattern.Expr = expression.Value{Val: v.Name} r, err := s.Pattern.Eval(ctx, nil) if err != nil { return errors.Trace(err) } match, ok := r.(bool) if !ok { return errors.Errorf("Eval like pattern error") } if !match { continue } } else if s.Where != nil { m := map[interface{}]interface{}{} m[expression.ExprEvalIdentFunc] = func(name string) (interface{}, error) { if strings.EqualFold(name, "Variable_name") { return v.Name, nil } return nil, errors.Errorf("unknown field %s", name) } match, err := expression.EvalBoolExpr(ctx, s.Where, m) if err != nil { return errors.Trace(err) } if !match { continue } } value := v.Value if !s.GlobalScope { // Try to get Session Scope variable value sv, ok := sessionVars.Systems[v.Name] if ok { value = sv } } row := &plan.Row{Data: []interface{}{v.Name, value}} s.rows = append(s.rows, row) } case stmt.ShowCollation: collations := charset.GetCollations() for _, v := range collations { if s.Pattern != nil { s.Pattern.Expr = expression.Value{Val: v.Name} r, err := s.Pattern.Eval(ctx, nil) if err != nil { return errors.Trace(err) } match, ok := r.(bool) if !ok { return errors.Errorf("Eval like pattern error") } if !match { continue } } else if s.Where != nil { m := map[interface{}]interface{}{} m[expression.ExprEvalIdentFunc] = func(name string) (interface{}, error) { switch { case strings.EqualFold(name, "Collation"): return v.Name, nil case strings.EqualFold(name, "Charset"): return v.CharsetName, nil case strings.EqualFold(name, "Id"): return v.ID, nil case strings.EqualFold(name, "Default"): if v.IsDefault { return "Yes", nil } return "", nil case strings.EqualFold(name, "Compiled"): return "Yes", nil case strings.EqualFold(name, "Sortlen"): // TODO: add sort length in Collation return 1, nil default: return nil, errors.Errorf("unknown field %s", name) } } match, err := expression.EvalBoolExpr(ctx, s.Where, m) if err != nil { return errors.Trace(err) } if !match { continue } } isDefault := "" if v.IsDefault { isDefault = "Yes" } row := &plan.Row{Data: []interface{}{v.Name, v.CharsetName, v.ID, isDefault, "Yes", 1}} s.rows = append(s.rows, row) } } return nil }
// Do implements plan.Plan Do interface. func (s *ShowPlan) Do(ctx context.Context, f plan.RowIterFunc) (err error) { switch s.Target { case stmt.ShowEngines: f(0, []interface{}{"InnoDB", "DEFAULT", "Supports transactions, row-level locking, and foreign keys", "YES", "YES", "YES"}) case stmt.ShowDatabases: dbs := sessionctx.GetDomain(ctx).InfoSchema().AllSchemaNames() // TODO: let information_schema be the first database sort.Strings(dbs) for _, d := range dbs { f(0, []interface{}{d}) } case stmt.ShowTables: is := sessionctx.GetDomain(ctx).InfoSchema() dbName := model.NewCIStr(s.DBName) if !is.SchemaExists(dbName) { return errors.Errorf("Can not find DB: %s", dbName) } // sort for tables var tableNames []string for _, v := range is.SchemaTables(dbName) { tableNames = append(tableNames, v.TableName().L) } sort.Strings(tableNames) for _, v := range tableNames { f(0, []interface{}{v}) } case stmt.ShowColumns: is := sessionctx.GetDomain(ctx).InfoSchema() dbName := model.NewCIStr(s.DBName) if !is.SchemaExists(dbName) { return errors.Errorf("Can not find DB: %s", dbName) } tbName := model.NewCIStr(s.TableName) tb, err := is.TableByName(dbName, tbName) if err != nil { return errors.Errorf("Can not find table: %s", s.TableName) } cols := tb.Cols() for _, col := range cols { if !s.isColOK(col) { continue } desc := column.NewColDesc(col) // The FULL keyword causes the output to include the column collation and comments, // as well as the privileges you have for each column. if s.Full { f(0, []interface{}{ desc.Field, desc.Type, desc.Collation, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, desc.Privileges, desc.Comment, }) } else { f(0, []interface{}{ desc.Field, desc.Type, desc.Null, desc.Key, desc.DefaultValue, desc.Extra, }) } } case stmt.ShowWarnings: // empty result case stmt.ShowCharset: // See: http://dev.mysql.com/doc/refman/5.7/en/show-character-set.html descs := charset.GetAllCharsets() for _, desc := range descs { row := []interface{}{desc.Name, desc.Desc, desc.DefaultCollation, desc.Maxlen} f(0, row) } case stmt.ShowVariables: sessionVars := variable.GetSessionVars(ctx) for _, v := range variable.SysVars { if s.Pattern != nil { p, ok := s.Pattern.(*expressions.PatternLike) if !ok { return errors.Errorf("Like should be a PatternLike expression") } p.Expr = expressions.Value{Val: v.Name} r, err := p.Eval(ctx, nil) if err != nil { return errors.Trace(err) } match, ok := r.(bool) if !ok { return errors.Errorf("Eval like pattern error") } if !match { continue } } value := v.Value if !s.GlobalScope { // Try to get Session Scope variable value sv, ok := sessionVars.Systems[v.Name] if ok { value = sv } } row := []interface{}{v.Name, value} f(0, row) } } return nil }