ariga / atlas-provider-gorm

GORM Provider for https://atlasgo.io
Apache License 2.0
52 stars 12 forks source link

How can I set up atlas to only migrate some models? #24

Open deerbone opened 8 months ago

deerbone commented 8 months ago

Hi, is there a way to set-up atlas to specify what models I want to exclude?

In our project we define some helper models that we do not migrate to the DB, we only work with them in the program itself.

Small example that doesn't really make sense:


// Model is a basic abstract db model struct. Custom Model to not utilize Gorm soft delete.
type Model struct {
    ID        uuid.UUID `gorm:"type:uuid;primaryKey"`
    CreatedAt time.Time `gorm:"not null"`
    UpdatedAt time.Time `gorm:"not null"`
}

type User struct {
    Model
    Name    string
    Surname string
}

type UserWithAddress struct {
    User    User   `gorm:"embedded"`
    Address string `gorm:"column:address"`
}
// main.go
package main

import ...

func main() {
    db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
    if err != nil {
        panic("failed to connect database")
    }

    // Migrate the schema
    if err := db.AutoMigrate(&model.User{}); err != nil {
        panic(err)
    }

    // Create a user with an embedded address
    user := model.UserWithAddress{
        User: model.User{
            Name:    "John",
            Surname: "Doe",
        },
        Address: "123 Main St.",
    }
    db.Create(&user)

    // Retrieve the user from the database
    var retrievedUser model.User
    db.First(&retrievedUser)

    // Print the retrieved user
    fmt.Printf("Retrieved User: %+v\n", retrievedUser)
}

atlas.hcl

data "external_schema" "gorm" {
  program = [
    "go",
    "run",
    "-mod=mod",
    "ariga.io/atlas-provider-gorm",
    "load",
    "--path", "./model",
    "--dialect", "sqlite", // mysql | postgres | sqlite
  ]
}

env "gorm" {
  src = data.external_schema.gorm.url
  dev = "sqlite://file?mode=memory"
  migration {
    dir = "file://migrations"
  }
  format {
    migrate {
      diff = "{{ sql . \"  \" }}"
    }
  }
  lint  {
    latest=10 // check against the latest 10 migrations
  }
}

What gets generated with atlas migrate diff


-- Create "user_with_addresses" table
CREATE TABLE `user_with_addresses` (
  `id` uuid NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  `name` text NULL,
  `surname` text NULL,
  `address` text NULL,
  PRIMARY KEY (`id`)
);
-- Create "models" table
CREATE TABLE `models` (
  `id` uuid NULL,
  `created_at` datetime NOT NULL,
  `updated_at` datetime NOT NULL,
  PRIMARY KEY (`id`)
);

The schema that GORM creates:


CREATE TABLE `users` (
    `id` uuid,
    `created_at` datetime NOT NULL,
    `updated_at` datetime NOT NULL,
    `name` text,
    `surname` text,
    PRIMARY KEY (`id`)
);

Is there a way for me to achieve this?

indeedhat commented 2 months ago

Um guessing at this point you have found a solution or given up but in case someone else ends up here:

It seems that atlas doesn't support the embedded struct tag at the moment, you can achieve what you want by embedding the struct itself, not ideal but its a stop gap until the embedded tag gets implemented

type UserWithAddress struct {
    User

    Address string `gorm:"column:address"`
}
rotemtam commented 2 months ago

Hey,

If you need something more involved, I suggest using Go Program Mode which give you ultimate control on the models the provider uses as the desired schema.