parse.go

 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}