I'm trying to create a POC for running Golang code migrations using goose
. The issue is that I'm using Ent framework, which seems in compatible for a straight forward use with goose
.
According to goose
docs and examples, it is possible to simply create a new Golang migration file using the command: goose create fetch_user_data go
.
The automatic boilerplate output is:
package migrations
import (
"database/sql"
"github.com/pressly/goose/v3"
)
func init() {
goose.AddMigration(Up, Down)
}
func Up(tx *sql.Tx) error {
_, err := tx.Exec("UPDATE users SET username='admin' WHERE username='root';")
if err != nil {
return err
}
return nil
}
func Down(tx *sql.Tx) error {
_, err := tx.Exec("UPDATE users SET username='root' WHERE username='admin';")
if err != nil {
return err
}
return nil
}
This means that once a Golang migration is running, the "Up" function gets a pointer to a transaction (*sql.Tx), allowing to run only a pure SQL query.
Now, I'm trying to modify the "Up" and "Down" function, to receive a pointer to the DB itself (*sql.DB), in order to create a new Ent client:
driver := entSQL.NewDriver("postgres", db.Conn(ctx))
client := ent.NewClient(ent.Driver(driver))
defer client.Close()
I've tried all kinds of ways as above, in order to create the Ent client but it seems that Ent cannot be initialized using a transaction pointer, and a higher level access pointer is needed instead.
From goose
docs, it seems that this can be achieved while using a custom Provider, in which it gets *sql.DB
based on given env vars. By connecting goose
library to that custom provider, it should be possible to modify the "Up" and "Down" function signatures as described.
To use a custom provider, it seems that I need to create my own goose
binary and register my migration files.
I haven't managed to find a good example which demonstrates how to do that. I'm looking for some guidance in order to understand how to do it.
Eventually, I want to be able to write the same goose create
command, as written above, and get an automatic boilerplate output which uses *sql.DB
instead of *sql.Tx
. If possible to get an Ent client directly, it is even better.
I tried various types for Ent client creation, based on *sql.Tx
, but it didn't work. I keep getting compilation errors, as goose
library by default is not familiar with entgo.io/ent/dialect/sql
, only with database/sql
, which is incompatible with Ent.
Please advise, thanks.
You could change the goose.AddMigration
to the goose.AddMigrationNoTxContext
in the migration's init
function and change the Up
and Down
signatures:
func init() {
goose.AddMigrationNoTxContext(Up, Down)
}
func Up(ctx context.Context, db *sql.DB) error {
// ...
return nil
}
func Down(ctx context.Context, db *sql.DB) error {
// ...
return nil
}