// CheckColumnType verifies that a given value is compatible // with the type requested by the column. If the value is a // placeholder, the type of the placeholder gets populated. func CheckColumnType(col ColumnDescriptor, val parser.Datum, args parser.MapArgs) error { if val == parser.DNull { return nil } var ok bool var err error var set parser.Datum switch col.Type.Kind { case ColumnType_BOOL: _, ok = val.(*parser.DBool) set, err = args.SetInferredType(val, parser.TypeBool) case ColumnType_INT: _, ok = val.(*parser.DInt) set, err = args.SetInferredType(val, parser.TypeInt) case ColumnType_FLOAT: _, ok = val.(*parser.DFloat) set, err = args.SetInferredType(val, parser.TypeFloat) case ColumnType_DECIMAL: _, ok = val.(*parser.DDecimal) set, err = args.SetInferredType(val, parser.TypeDecimal) case ColumnType_STRING: _, ok = val.(*parser.DString) set, err = args.SetInferredType(val, parser.TypeString) case ColumnType_BYTES: _, ok = val.(*parser.DBytes) if !ok { _, ok = val.(*parser.DString) } set, err = args.SetInferredType(val, parser.TypeBytes) case ColumnType_DATE: _, ok = val.(*parser.DDate) set, err = args.SetInferredType(val, parser.TypeDate) case ColumnType_TIMESTAMP: _, ok = val.(*parser.DTimestamp) set, err = args.SetInferredType(val, parser.TypeTimestamp) case ColumnType_TIMESTAMPTZ: _, ok = val.(*parser.DTimestampTZ) set, err = args.SetInferredType(val, parser.TypeTimestampTZ) case ColumnType_INTERVAL: _, ok = val.(*parser.DInterval) set, err = args.SetInferredType(val, parser.TypeInterval) default: return util.Errorf("unsupported column type: %s", col.Type.Kind) } // Check that the value cast has succeeded. // We ignore the case where it has failed because val was a DArg, // which is signalled by SetInferredType returning a non-nil assignment. if !ok && set == nil { return fmt.Errorf("value type %s doesn't match type %s of column %q", val.Type(), col.Type.Kind, col.Name) } return err }
// marshalColumnValue returns a Go primitive value equivalent of val, of the // type expected by col. If val's type is incompatible with col, or if // col's type is not yet implemented, an error is returned. func marshalColumnValue(col ColumnDescriptor, val parser.Datum, args parser.MapArgs) (interface{}, error) { if val == parser.DNull { return nil, nil } switch col.Type.Kind { case ColumnType_BOOL: if v, ok := val.(parser.DBool); ok { return bool(v), nil } if set, err := args.SetInferredType(val, parser.DummyBool); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_INT: if v, ok := val.(parser.DInt); ok { return int64(v), nil } if set, err := args.SetInferredType(val, parser.DummyInt); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_FLOAT: if v, ok := val.(parser.DFloat); ok { return float64(v), nil } if set, err := args.SetInferredType(val, parser.DummyFloat); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_DECIMAL: if v, ok := val.(*parser.DDecimal); ok { return v.Dec, nil } if set, err := args.SetInferredType(val, parser.DummyDecimal); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_STRING: if v, ok := val.(parser.DString); ok { return string(v), nil } if set, err := args.SetInferredType(val, parser.DummyString); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_BYTES: if v, ok := val.(parser.DBytes); ok { return string(v), nil } if v, ok := val.(parser.DString); ok { return string(v), nil } if set, err := args.SetInferredType(val, parser.DummyBytes); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_DATE: if v, ok := val.(parser.DDate); ok { return int64(v), nil } if set, err := args.SetInferredType(val, parser.DummyDate); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_TIMESTAMP: if v, ok := val.(parser.DTimestamp); ok { return v.Time, nil } if set, err := args.SetInferredType(val, parser.DummyTimestamp); err != nil { return nil, err } else if set != nil { return nil, nil } case ColumnType_INTERVAL: if v, ok := val.(parser.DInterval); ok { return v.Duration, nil } if set, err := args.SetInferredType(val, parser.DummyInterval); err != nil { return nil, err } else if set != nil { return nil, nil } default: return nil, util.Errorf("unsupported column type: %s", col.Type.Kind) } return nil, fmt.Errorf("value type %s doesn't match type %s of column %q", val.Type(), col.Type.Kind, col.Name) }