Skip to content
This repository has been archived by the owner on Mar 12, 2024. It is now read-only.

Commit

Permalink
fix: unterminated up statement is ignored (pressly#558)
Browse files Browse the repository at this point in the history
  • Loading branch information
mfridman authored Jul 7, 2023
1 parent 843a23d commit 06ff963
Show file tree
Hide file tree
Showing 7 changed files with 48 additions and 2 deletions.
4 changes: 3 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [Unreleased]

- Fix pre-built binary versioning and make small improvements to the build process.
- Fix pre-built binary versioning and make small improvements to GoReleaser config.
- Fix an edge case in the `sqlparser` where the last up statement may be ignored if it's
unterminated and followed by a `-- +goose Down` annotation.

## [v3.13.1] - 2023-07-03

Expand Down
16 changes: 15 additions & 1 deletion internal/sqlparser/parser.go
Original file line number Diff line number Diff line change
Expand Up @@ -127,6 +127,12 @@ func ParseSQLMigration(r io.Reader, direction Direction, debug bool) (stmts []st
case "+goose Down":
switch stateMachine.get() {
case gooseUp, gooseStatementEndUp:
// If we hit a down annotation, but the buffer is not empty, we have an unfinished SQL query from a
// previous up annotation. This is an error, because we expect the SQL query to be terminated by a semicolon
// and the buffer to have been reset.
if bufferRemaining := strings.TrimSpace(buf.String()); len(bufferRemaining) > 0 {
return nil, false, missingSemicolonError(stateMachine.state, direction, bufferRemaining)
}
stateMachine.set(gooseDown)
default:
return nil, false, fmt.Errorf("must start with '-- +goose Up' annotation, stateMachine=%d, see https://github.com/pressly/goose#sql-migrations", stateMachine.state)
Expand Down Expand Up @@ -238,12 +244,20 @@ func ParseSQLMigration(r io.Reader, direction Direction, debug bool) (stmts []st
}

if bufferRemaining := strings.TrimSpace(buf.String()); len(bufferRemaining) > 0 {
return nil, false, fmt.Errorf("failed to parse migration: state %d, direction: %v: unexpected unfinished SQL query: %q: missing semicolon?", stateMachine.state, direction, bufferRemaining)
return nil, false, missingSemicolonError(stateMachine.state, direction, bufferRemaining)
}

return stmts, useTx, nil
}

func missingSemicolonError(state parserState, direction Direction, s string) error {
return fmt.Errorf("failed to parse migration: state %d, direction: %v: unexpected unfinished SQL query: %q: missing semicolon?",
state,
direction,
s,
)
}

// cleanupStatement attempts to find the last semicolon and trims
// the remaining chars from the input string. This is useful for cleaning
// up a statement containing trailing comments or empty lines.
Expand Down
16 changes: 16 additions & 0 deletions internal/sqlparser/parser_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,22 @@ func TestSplitStatements(t *testing.T) {
}
}

func TestInvalidUp(t *testing.T) {
t.Parallel()

testdataDir := filepath.Join("testdata", "invalid", "up")
entries, err := os.ReadDir(testdataDir)
check.NoError(t, err)
check.NumberNotZero(t, len(entries))

for _, entry := range entries {
by, err := os.ReadFile(filepath.Join(testdataDir, entry.Name()))
check.NoError(t, err)
_, _, err = ParseSQLMigration(strings.NewReader(string(by)), DirectionUp, false)
check.HasError(t, err)
}
}

func TestUseTransactions(t *testing.T) {
t.Parallel()

Expand Down
5 changes: 5 additions & 0 deletions internal/sqlparser/testdata/invalid/up/a.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
-- +goose Up
SELECT * FROM foo;
SELECT * FROM bar
-- +goose Down
SELECT * FROM baz;
4 changes: 4 additions & 0 deletions internal/sqlparser/testdata/invalid/up/b.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
-- +goose Up
SELECT * FROM bar
-- +goose Down
SELECT * FROM baz;
3 changes: 3 additions & 0 deletions internal/sqlparser/testdata/invalid/up/c.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
-- +goose Up
SELECT * FROM bar
-- +goose Down
2 changes: 2 additions & 0 deletions internal/sqlparser/testdata/invalid/up/d.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
-- +goose Up
SELECT * FROM bar

0 comments on commit 06ff963

Please sign in to comment.