-
-
Notifications
You must be signed in to change notification settings - Fork 233
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add something like GORM's AutoMigrate #456
Comments
+1 |
@vmihailenco I've been reading through the issues and noticed this one had |
@bevzzz The help is welcome here, but you should be warned that this is not a small issue and it will probably require several weeks of work. If you decide to work on this, my advice would be to learn how GORM AutoMigrate works and what we can learn from it. Writing your thoughts here so others can help would be the next step. I did not have a chance to learn from GORM AutoMigrate yet, but I guess the plan should look like this:
package pgdialect
func (Dialect) RenameColumn(...)
func (Dialect) ChangeColumnType(...)
Each step can be done separately so we have a chance to send feedback at the earlier stage. Also pinging @dizzyfool and @LdDl who done some excellent work on https://github.com/dizzyfool/genna and https://github.com/LdDl/bungen and might be interested to help designing the API for step 1. |
@vmihailenco Thanks for getting back in touch so quickly! P.S. I plan to start working on it on the next weekend, I guess we are not in a rush here, right? |
No rush for sure. Even making some progress on step 1) will make a change in the long run. |
TLDR: just bunch of SQL queries to extract reference information about Postgres tables and my first-look thoughts My POV:
p.s. Recently I was impressed by this project https://github.com/kyleconroy/sqlc . Could be very cool to add something like this for ORM purposes based on SQL migrations files...but I guess this sounds like a new topic? |
👍 We need to start with something small and grow it up so it works at least for SQLite and Postgres which have a lot in common. Most likely we should start by familiarizing ourselves with the API already provided by database/sql, e.g. https://pkg.go.dev/database/sql/driver#RowsColumnTypeDatabaseTypeName
Yeah, projects like sqlc and Ents open a whole new world of code generation for you :) |
@vmihailenco I wasn't able to look into that yet because I had a lot of work in the past couple of months. |
@bevzzz take your time :) |
Here are my thoughts on how this feature could be implemented. It felt like a lot of ground to cover, so if some concepts need more clarification/discussion, please let me know. I am planning to follow the steps suggested above, starting with Postgres: 1. Improve Bun dialects with ability to inspect database schemaFor this step I think we'll need the following: package inspect
type Inspector interface {
Tables() []*Table
HasTable(table interface{}) bool
HasColumn(table interface{}, column string) bool
}
// Not sure if there should be an interface for that, can't think of different implementations
type Table struct {
ParentSchema string
Name string
Columns []Column
}
// Each dialect can implement Column to handle the specifics
type Column interface {
Type() *sql.ColumnType
// Is the database column equivalent to the column definition in the Go-model?
// Do we need to alter this column in migration?
Equivalent(schema.Field) bool
// Additional metadata that's not available in sql.ColumnType
IsPK() bool
IsAutoincrement() bool
}
2. Support
|
Started working on
The way I see it, the scope of
(Have I missed anything?*) While it's not the first priority, I was thinking about the db.NewAlterTable().Model().AddColumn() // ALTER TABLE model ADD COLUMN col
db.NewAlterTable().Model().DropColumn() // ALTER TABLE model DROP COLUMN col *There're also Table relations, but I haven' t gotten to that yet. I don't suppose |
Thanks for writing so many details 👍 I agree that we should start with adding a table inspector - perhaps just an ability to list columns in a table should be enough.
Looks reasonable and it is hard to tell more without writing some code and getting your hands dirty. I would suggest to name the package Regarding the API, I expect to have something like: import "github.com/uptrace/bun/sqlschema"
var db *bun.DB
inspector := sqlschema.NewInspector(db)
columns, err := inspector.Columns(ctx, tableName)
// err can be sqlschema.ErrNotExists if the table is missing
// columns is []sqlschema.Column
I think we need something like this to build SQL queries: db.NewAlterTable().Model(...).AddColumn("").Opt1().Opt2().Exec(ctx)
db.NewAlterTable().Model(...).DropColumn("").Opt1().Opt2().Exec(ctx) But it will get too complex very soon with RDMBS-specific features/options so we should also support something much simpler just for var db *bun.DB
migrator := sqlschema.NewMigrator(db)
err := migrator.AddColumn(&somepkg.Column{
Schema: "", // optional
Table: "table_name",
Column: "column_name",
Type: ...,
})
err := migrator.DropColumn(col)
err := migrator.ChangeType(col, newType) Underneath, it may use Bun API to generate the query or just generate and execute SQL directly.
It probably can be supported via a tag like you suggested |
I have created a draft PR (it is very much WIP) so that we could exchange ideas with specific code at hand. I'm also not sure if some of my code breaks the project's code style, so if it does, please let me know how I could change it. It only includes Appreciate your suggestions a lot, and looking forward to hearing your feedback on the progress so-far! |
Just left a code review and some suggestions. Most of them are just thoughts from the top of my head so please be patient with me :) And thanks for working on this! |
Found this bug while working on it, so I guess I'll do a PR for that first, because I'd like to use some of the underlying functionality for |
I opened a PR which adds schema inspection and I took a look at how GORM, ent, and django handle this and tried to come up with a solution that fits bun's existing APIs. The scope of changes we want to support is pretty much that what can be described in a bun.Model:
The tricky part will be resolving dependencies between different migrations (e.g. create table before referencing it in an FK constraint). Additionally, it would be nice to provide some options like:
|
First, we should provide some unified way to inspect current database schema via using
INFORMATION_SCHEMA.TABLES
or something similar. Then we can sync the database by comparing the actual database schema with available Go models.The text was updated successfully, but these errors were encountered: