I can't find it now

https://github.com/jinzhu/gorm/issues/628 it was supported in the past, right?

Comment From: qshuai

Yeah. Refer to the following example:

type Ecosystem string

const (
    Production Ecosystem = "production"
    TestSystem Ecosystem = "testsystem"
)

func (e *Ecosystem) Scan(value interface{}) error {
    *e = Ecosystem(value.([]byte))
    return nil
}

func (e Ecosystem) Value() (driver.Value, error) {
    return string(e), nil
}

// model define
Ecosystem        Ecosystem `json:"ecosystem" sql:"type:ENUM('production', 'testsystem')"`

Comment From: paqio

getting pq: type "enum" does not exist Any solutions?

Comment From: Entrio

same here, a whole quest to find an answer

Comment From: AlexThurston

Anyone find an answer to this?

Comment From: 4nte

+1?

Comment From: friend0

I'm not able to use enums in postgres either. @qshuai the above example is non-op

Comment From: qshuai

The sample works for me, but in mysql. postgres have not been tested.

Comment From: friend0

Hmm, it would be good to get another pg user to verify, but looks like this may be missing functionality? I could maybe take a look at a PR if someone else can verify it's not user error

Comment From: MithunArunan

Getting the same error, pq: type "enum" does not exist

Comment From: atoami

Is there any updates for this issue? We need to resolve this issue ASAP.

Comment From: sillygod

For postgresql, you should define the type in the struct tag as the following

ex.

type XXX struct {
    Platform            DevicePlatform      `sql:"type:platform"`
}

platform is a data type as enum in my case. You should use the data type instead of type:ENUM(... in the struct tag.

Comment From: atoami

@sillygod Can you upload full example please? For instance, with enum of platform("ios", "android"). Thanks.

Comment From: sillygod

@sillygod Can you upload full example please? For instance, with enum of platform("ios", "android"). Thanks.

Hi @atoami, I have to say if you want to use the gorm's auto migration with the enum in PostgreSQL, it will not work. However, you can perform CRUD with enum in PostgreSQL.

First, let's prepare the database, I create the enum manually.

CREATE TYPE phone_model AS ENUM (
    'unknown',
    'sony',
    'pixel');

Then define the example model.

type phoneModel string

const (
    sony  phoneModel = "sony"
    pixel phoneModel = "pixel"
)

func (p *phoneModel) Scan(value interface{}) error {
    *p = phoneModel(value.([]byte))
    return nil
}

func (p phoneModel) Value() (driver.Value, error) {
    return string(p), nil
}

type Phone struct {
    gorm.Model
    Name       string
    PhoneModel phoneModel `sql:"type:phone_model"`
}

func (Phone) TableName() string {
    return "phone"
}

The key point is to use sql:"type:phone_model" instead. You will get pq: type "enum" does not exist if you try to use sql:"enum('unknown', 'sony', 'pixel')".

Because the enum is defined at first, you can use gorm's AutoMigration to create table here.

db.AutoMigrate(&Phone{})

Finally, you can test about inserting a new row.

if err := db.Create(&Phone{
    Name:       "alice",
    PhoneModel: sony,
}).Error; err != nil {
    panic(err)
}

Comment From: github-actions[bot]

This issue will be automatically closed because it is marked as GORM V1 issue, we have released the public testing GORM V2 release and its documents https://v2.gorm.io/docs/ already, the testing release has been used in some production services for a while, and going to release the final version in following weeks, we are still actively collecting feedback before it, please open a new issue for any suggestion or problem, thank you

Also check out https://github.com/go-gorm/gorm/wiki/GORM-V2-Release-Note-Draft for how to use the public testing version and its changelog

Comment From: ykchong45

I found on a Chinese site that the following syntax works for MySQL enum type definition: gorm:"type:enum('published', 'pending', 'deleted');default:'pending'"

Comment From: bluebrown

I found on a Chinese site that the following syntax works for MySQL enum type definition: gorm:"type:enum('published', 'pending', 'deleted');default:'pending'"

This didnt work for me. I stumm got type enum does not exist.

Comment From: nielvid

I found on a Chinese site that the following syntax works for MySQL enum type definition: gorm:"type:enum('published', 'pending', 'deleted');default:'pending'"

This works for me in mysql

Comment From: Linchin

Why does this type definition start with lower case? Is it because we don't want this type to be public?

type phoneModel string

Comment From: ilhm-rai

for postgresql declare this syntax before auto migration

db.Debug().Exec(`
    DO $$ BEGIN
        CREATE TYPE enum_name AS ENUM ('value1', 'value2');
    EXCEPTION
        WHEN duplicate_object THEN null;
    END $$;`)

db.Debug().AutoMigrate(...)

Comment From: abishz17

sql:"type:enum('Published', 'Pending', 'Deleted');default:'Pending'" This tag works perfectly with gorm's automigrate in postgres.

Comment From: nkbhasker

I have recently done something like this with Atlas.

Define enum

type GenderEnum string
const (
    MALE   GenderEnum = "MALE"
    FEMALE GenderEnum = "FEMALE"
)

func (e *GenderEnum) Scan(value interface{}) error {
    str, ok := value.(string)
    if !ok {
        return fmt.Errorf("invalid str")
    }
    *e = GenderEnum(str)

    return nil
}

func (e GenderEnum) Value() (interface{}, error) {
    return string(e), nil
}

Define model with enum field

type User struct {
    gorm.Model
    Name   string
    Email  string
    Gender *enums.GenderEnum `gorm:"type:gender"`
}

Create a migration script with enums and models

func main() {
    sb := &strings.Builder{}
    loadEnums(sb)
    loadModels(sb)

    io.WriteString(os.Stdout, sb.String())
}

func loadEnums(sb *strings.Builder) {
    enums := []string{
        `CREATE TYPE gender AS ENUM (
            'MALE',
            'FEMALE'
        );`,
    }
    for _, enum := range enums {
        sb.WriteString(enum)
        sb.WriteString(";\n")
    }
}

func loadModels(sb *strings.Builder) {
    models := []interface{}{
        &models.User{},
    }
    stmts, err := gormschema.New("postgres").Load(models...)
    if err != nil {
        fmt.Fprintf(os.Stderr, "failed to load gorm schema: %v\n", err)
        os.Exit(1)
    }
    sb.WriteString(stmts)
    sb.WriteString(";\n")
}

Create an atlas.hcl file

data "external_schema" "gorm" {
  program = ["go", "run", "./migrate.go"]
}

env "gorm" {
  src = data.external_schema.gorm.url
  dev = "docker://postgres/16/dev"
  migration {
    dir = "file://migrations"
  }

  format {
    migrate {
      diff = "{{ sql . \"  \" }}"
    }
  }
}

Link to example repository go-gorm-atlas-example