Implement shell "database" driver
I've been thinking about this for quite some time. I think the root issue why this issue has not been fixed is that the Driver interface is too broad in scope. Really, it has two orthogonal responsibilities:
- To run the actual migrations, ie. run the shell command,
ALTERa table etc. - To keep track of which migrations have been applied, lock database and mark migrations as applied etc.
To avoid having to implement a "shell driver" for every database backend, I instead propose that Driver is split up into two interfaces; (for now) call them Migrator and MigrationRepository:
type Migrator interface {
Open(url string) (Driver, error)
Close() error
Run(migration io.Reader) error
}
type MigrationRepository interface {
Open(url string) (Driver, error)
Close() error
Lock() error
Unlock() error
SetVersion(version int, dirty bool) error
Version() (version int, dirty bool, err error)
Drop() error
}
The nice thing is that all Driver implementations already implement these two interfaces. One challenge is that Open(...) and Close() only are supposed to be called once per implementation. This could be worked around by wrapping all Driver implementations in a SingleOpenCloseDriver which makes sure to only delegate Open/Close calls to the actual delegate if not called before. As soon as all Drivers have been split up into two different implementations, SingleOpenCloseDriver can be ditched.
Clearly, this change would also require that CLI would take a -migrator and a -repository URLs to define which migrator and database that should be used. For backwards compatibility -database could hang around, and be a shortcut for setting -migrator and -repository to the same value.
What are you thoughts on this?
I think there is a misunderstanding. When I wrote shell I meant bash.
For your specific case, I believe the source driver is the equivalent to your proposed Migrator interface.
@mattes Hm, so if shell is implemented, where can I find it? https://github.com/mattes/migrate/tree/master/database/shell seem to be empty.
The bash/shell driver is not yet implemented.
@mattes Still, if you would implement bash, how would you store which migrations have been executed?