Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

unsupported data type: &[] error on GORM field where custom Valuer returns nil?

Tags:

I was trying to create a GORM model for a postgres database, containing a type with a custom Scanner and Valuer that converts a string slice to and from a string, to be saved as a single database column. If the slice is either empty or nil, I want the database column to also be nil (as opposed to an empty string).

type MultiString []string

func (s *MultiString) Scan(src interface{}) error {
    str, ok := src.(string)
    if !ok {
        return errors.New("failed to scan multistring field - source is not a string")
    }
    *s = strings.Split(str, ",")
    return nil
}

func (s MultiString) Value() (driver.Value, error) {
    if s == nil || len(s) == 0 {
        return nil, nil
    }
    return strings.Join(s, ","), nil
}

The problem arises when I try and call AutoMigrate on the following struct:

type Person struct {
    ID      int
    Name    string
    Kids    *MultiString
}

I get the following errors multiple times:

[error] unsupported data type: &[]
like image 964
robbieperry22 Avatar asked Sep 23 '20 19:09

robbieperry22


People also ask

Which data type is not supported in Snowflake?

BINARY can be used instead; maximum of 8,388,608 bytes. For more information, see String & Binary Data Types. VARCHAR can be used instead; maximum of 16,777,216 bytes (for singlebyte).


1 Answers

In the Value method, replace the returned nil with sql.NullString{} - This is incorrect, as Value should not return another Valuer.

The problem is that GORM is unsure of what the datatype should be for the newly defined type, so it tried to figure it out. Instead, the type should be explicitly defined, either with a tag in the model or by implementing a gorm method on the new type

Tag in the model

type MyModel struct {
    ...
    MyText MultiString `gorm:"type:text"`
}

This tells GORM to use the type text for the DB column type. With this strategy, the tag must be applied every time the new type is used in a model.

GORM Methods

Two GORM methods can be implemented on the new data type to tell GORM what database type should be used:

  • GormDataType() string
  • GormDBDataType(db *gorm.DB, field *schema.Field) string

Examples:

func (MultiString) GormDataType() string {
  return "text"
}
func (MultiString) GormDBDataType(db *gorm.DB, field *schema.Field) string {

  // returns different database type based on driver name
  switch db.Dialector.Name() {
  case "mysql", "sqlite":
    return "text"
  }
  return ""
}

This one is useful for if the data type differs between what type of database you're using.

like image 113
robbieperry22 Avatar answered Sep 23 '22 17:09

robbieperry22