-
Notifications
You must be signed in to change notification settings - Fork 530
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
feat: postgres migration table existence check (#860)
- Loading branch information
Showing
9 changed files
with
188 additions
and
33 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
package database | ||
|
||
import "context" | ||
|
||
// StoreExtender is an extension of the Store interface that provides optional optimizations and | ||
// database-specific features. While not required by the core goose package, implementing these | ||
// methods can improve performance and functionality for specific databases. | ||
// | ||
// IMPORTANT: This interface may be expanded in future versions. Implementors MUST be prepared to | ||
// update their implementations when new methods are added, either by implementing the new | ||
// functionality or returning [errors.ErrUnsupported]. | ||
// | ||
// The goose package handles these extended capabilities through a [controller.StoreController], | ||
// which automatically uses optimized methods when available while falling back to default behavior | ||
// when they're not implemented. | ||
// | ||
// Example usage to verify implementation: | ||
// | ||
// var _ StoreExtender = (*CustomStoreExtended)(nil) | ||
// | ||
// In short, it's exported to allows implementors to have a compile-time check that they are | ||
// implementing the interface correctly. | ||
type StoreExtender interface { | ||
Store | ||
|
||
// TableExists checks if the migrations table exists in the database. Implementing this method | ||
// allows goose to optimize table existence checks by using database-specific system catalogs | ||
// (e.g., pg_tables for PostgreSQL, sqlite_master for SQLite) instead of generic SQL queries. | ||
// | ||
// Return [errors.ErrUnsupported] if the database does not provide an efficient way to check | ||
// table existence. | ||
TableExists(ctx context.Context, db DBTxConn) (bool, error) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package controller | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
|
||
"github.com/pressly/goose/v3/database" | ||
) | ||
|
||
// A StoreController is used by the goose package to interact with a database. This type is a | ||
// wrapper around the Store interface, but can be extended to include additional (optional) methods | ||
// that are not part of the core Store interface. | ||
type StoreController struct{ database.Store } | ||
|
||
var _ database.StoreExtender = (*StoreController)(nil) | ||
|
||
// NewStoreController returns a new StoreController that wraps the given Store. | ||
// | ||
// If the Store implements the following optional methods, the StoreController will call them as | ||
// appropriate: | ||
// | ||
// - TableExists(context.Context, DBTxConn) (bool, error) | ||
// | ||
// If the Store does not implement a method, it will either return a [errors.ErrUnsupported] error | ||
// or fall back to the default behavior. | ||
func NewStoreController(store database.Store) *StoreController { | ||
return &StoreController{store} | ||
} | ||
|
||
func (c *StoreController) TableExists(ctx context.Context, db database.DBTxConn) (bool, error) { | ||
if t, ok := c.Store.(interface { | ||
TableExists(ctx context.Context, db database.DBTxConn) (bool, error) | ||
}); ok { | ||
return t.TableExists(ctx, db) | ||
} | ||
return false, errors.ErrUnsupported | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters