1package sqlparser
2
3import (
4 "fmt"
5 "io/fs"
6
7 "go.uber.org/multierr"
8 "golang.org/x/sync/errgroup"
9)
10
11type ParsedSQL struct {
12 UseTx bool
13 Up, Down []string
14}
15
16func ParseAllFromFS(fsys fs.FS, filename string, debug bool) (*ParsedSQL, error) {
17 parsedSQL := new(ParsedSQL)
18 // TODO(mf): parse is called twice, once for up and once for down. This is inefficient. It
19 // should be possible to parse both directions in one pass. Also, UseTx is set once (but
20 // returned twice), which is unnecessary and potentially error-prone if the two calls to
21 // parseSQL disagree based on direction.
22 var g errgroup.Group
23 g.Go(func() error {
24 up, useTx, err := parse(fsys, filename, DirectionUp, debug)
25 if err != nil {
26 return err
27 }
28 parsedSQL.Up = up
29 parsedSQL.UseTx = useTx
30 return nil
31 })
32 g.Go(func() error {
33 down, _, err := parse(fsys, filename, DirectionDown, debug)
34 if err != nil {
35 return err
36 }
37 parsedSQL.Down = down
38 return nil
39 })
40 if err := g.Wait(); err != nil {
41 return nil, err
42 }
43 return parsedSQL, nil
44}
45
46func parse(fsys fs.FS, filename string, direction Direction, debug bool) (_ []string, _ bool, retErr error) {
47 r, err := fsys.Open(filename)
48 if err != nil {
49 return nil, false, err
50 }
51 defer func() {
52 retErr = multierr.Append(retErr, r.Close())
53 }()
54 stmts, useTx, err := ParseSQLMigration(r, direction, debug)
55 if err != nil {
56 return nil, false, fmt.Errorf("failed to parse %s: %w", filename, err)
57 }
58 return stmts, useTx, nil
59}