mirror of https://github.com/pressly/goose.git
60 lines
1.4 KiB
Go
60 lines
1.4 KiB
Go
package sqlparser
|
|
|
|
import (
|
|
"fmt"
|
|
"io/fs"
|
|
|
|
"go.uber.org/multierr"
|
|
"golang.org/x/sync/errgroup"
|
|
)
|
|
|
|
type ParsedSQL struct {
|
|
UseTx bool
|
|
Up, Down []string
|
|
}
|
|
|
|
func ParseAllFromFS(fsys fs.FS, filename string, debug bool) (*ParsedSQL, error) {
|
|
parsedSQL := new(ParsedSQL)
|
|
// TODO(mf): parse is called twice, once for up and once for down. This is inefficient. It
|
|
// should be possible to parse both directions in one pass. Also, UseTx is set once (but
|
|
// returned twice), which is unnecessary and potentially error-prone if the two calls to
|
|
// parseSQL disagree based on direction.
|
|
var g errgroup.Group
|
|
g.Go(func() error {
|
|
up, useTx, err := parse(fsys, filename, DirectionUp, debug)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
parsedSQL.Up = up
|
|
parsedSQL.UseTx = useTx
|
|
return nil
|
|
})
|
|
g.Go(func() error {
|
|
down, _, err := parse(fsys, filename, DirectionDown, debug)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
parsedSQL.Down = down
|
|
return nil
|
|
})
|
|
if err := g.Wait(); err != nil {
|
|
return nil, err
|
|
}
|
|
return parsedSQL, nil
|
|
}
|
|
|
|
func parse(fsys fs.FS, filename string, direction Direction, debug bool) (_ []string, _ bool, retErr error) {
|
|
r, err := fsys.Open(filename)
|
|
if err != nil {
|
|
return nil, false, err
|
|
}
|
|
defer func() {
|
|
retErr = multierr.Append(retErr, r.Close())
|
|
}()
|
|
stmts, useTx, err := ParseSQLMigration(r, direction, debug)
|
|
if err != nil {
|
|
return nil, false, fmt.Errorf("failed to parse %s: %w", filename, err)
|
|
}
|
|
return stmts, useTx, nil
|
|
}
|