Beispiel #1
0
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
}
Beispiel #2
0
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})
			}
		}
	}
}
Beispiel #3
0
// Set ResultField info according to values
// This is used for inferring calculated fields type/Flen/charset
// For example "select count(*) from t;" will return a ResultField with type TypeLonglong, charset binary and Flen 21.
func setResultFieldInfo(fields []*field.ResultField, values []interface{}) error {
	if len(fields) != len(values) {
		return errors.Errorf("Fields and Values length unmatch %d VS %d", len(fields), len(values))
	}
	for i, rf := range fields {
		if rf.Col.Tp == 0 {
			// 0 == TypeDecimal, Tp maybe uninitialized
			rf.Col.Charset = charset.CharsetBin
			rf.Col.Collate = charset.CharsetBin
			c := values[i]
			switch v := c.(type) {
			case int8, int16, int, int32, int64:
				rf.Col.Tp = mysql.TypeLonglong
			case uint8, uint16, uint, uint32, uint64:
				rf.Col.Tp = mysql.TypeLonglong
				rf.Col.Flag |= mysql.UnsignedFlag
			case float32, float64:
				rf.Col.Tp = mysql.TypeFloat
			case string:
				rf.Col.Tp = mysql.TypeVarchar
				rf.Col.Flen = len(v)
				rf.Col.Charset = mysql.DefaultCharset
				rf.Col.Collate = mysql.DefaultCollationName
			case []byte:
				rf.Col.Tp = mysql.TypeBlob
			case mysql.Time:
				rf.Col.Tp = v.Type
			case mysql.Duration:
				rf.Col.Tp = mysql.TypeDuration
			case mysql.Decimal:
				rf.Col.Tp = mysql.TypeDecimal
			default:
				return errors.Errorf("Unknown type %T", c)
			}
			if rf.Col.Flen == 0 {
				rf.Col.Flen = mysql.GetDefaultFieldLength(rf.Col.Tp)
			}
			// TODO: set flags
		}
	}
	return nil
}
Beispiel #4
0
// ColumnDefToCol converts 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 == 0 {
		col.Flen = mysql.GetDefaultFieldLength(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 !expressions.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.
			}
		}
	}

	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
}