diff --git a/.github/workflows/go.yml b/.github/workflows/go.yml index aa28174..17784a4 100644 --- a/.github/workflows/go.yml +++ b/.github/workflows/go.yml @@ -43,7 +43,12 @@ jobs: run: go vet -v $(go list ./... | grep -v "github.com/tursodatabase/libsql-client-go/sqliteparser$") - name: Install sqlclosecheck - run: go install github.com/ryanrolds/sqlclosecheck@latest + run: | + if [ "${{ matrix.go }}" = "1.20" ]; then + go install github.com/ryanrolds/sqlclosecheck@v0.5.1 + else + go install github.com/ryanrolds/sqlclosecheck@v0.6.0 + fi - name: sqlclosecheck run: go vet -vettool=${HOME}/go/bin/sqlclosecheck ./... diff --git a/sqliteparserutils/utils.go b/sqliteparserutils/utils.go index eab4e1a..4341e3e 100644 --- a/sqliteparserutils/utils.go +++ b/sqliteparserutils/utils.go @@ -27,6 +27,8 @@ func (iterator *StatementIterator) Next() (statement string, extraInfo SplitStat var ( insideCreateTriggerStmt = false insideMultilineComment = false + sawTriggerBegin = false + triggerBlockDepth = 0 startPosition = -1 previousToken = iterator.currentToken ) @@ -47,9 +49,22 @@ func (iterator *StatementIterator) Next() (statement string, extraInfo SplitStat insideCreateTriggerStmt = atCreateTriggerStart(iterator.tokenizer) startPosition = iterator.currentToken.GetStart() } else if insideCreateTriggerStmt { - // extend trigger creation statement to include END token after last semicolon - if iterator.currentToken.GetTokenType() == sqliteparser.SQLiteLexerEND_ { - insideCreateTriggerStmt = false + tokenType := iterator.currentToken.GetTokenType() + if !sawTriggerBegin { + if tokenType == sqliteparser.SQLiteLexerBEGIN_ { + sawTriggerBegin = true + triggerBlockDepth = 1 + } + } else { + switch tokenType { + case sqliteparser.SQLiteLexerCASE_: + triggerBlockDepth++ + case sqliteparser.SQLiteLexerEND_: + triggerBlockDepth-- + if triggerBlockDepth == 0 { + insideCreateTriggerStmt = false + } + } } } else if iterator.currentToken.GetTokenType() == sqliteparser.SQLiteLexerSCOL { // finish current statement (don't forget to consume as we are breaking here) diff --git a/sqliteparserutils/utils_test.go b/sqliteparserutils/utils_test.go index ed21edf..708080a 100644 --- a/sqliteparserutils/utils_test.go +++ b/sqliteparserutils/utils_test.go @@ -163,6 +163,27 @@ func TestSplitStatement(t *testing.T) { stmts: []string{"CREATE TEMP TRIGGER update_updated_at AFTER UPDATE ON users FOR EACH ROW BEGIN UPDATE users SET updated_at = 0 WHERE id = NEW.id; END"}, extraInfo: generateSimpleSplitStatementExtraInfo(sqliteparser.SQLiteLexerEND_), }, + { + name: "CompleteCreateTriggerStatementWithCaseEndInBody", + value: "CREATE TRIGGER my_trigger BEFORE INSERT ON my_table BEGIN SELECT CASE WHEN TRUE THEN FALSE END; END;", + stmts: []string{"CREATE TRIGGER my_trigger BEFORE INSERT ON my_table BEGIN SELECT CASE WHEN TRUE THEN FALSE END; END"}, + extraInfo: generateSimpleSplitStatementExtraInfo(sqliteparser.SQLiteLexerSCOL), + }, + { + name: "CompleteCreateTriggerStatementWithCaseEndInWhenClause", + value: "CREATE TRIGGER my_trigger BEFORE INSERT ON my_table WHEN CASE WHEN NEW.id > 0 THEN 1 ELSE 0 END = 1 BEGIN SELECT 1; END", + stmts: []string{"CREATE TRIGGER my_trigger BEFORE INSERT ON my_table WHEN CASE WHEN NEW.id > 0 THEN 1 ELSE 0 END = 1 BEGIN SELECT 1; END"}, + extraInfo: generateSimpleSplitStatementExtraInfo(sqliteparser.SQLiteLexerEND_), + }, + { + name: "CreateTriggerWithCaseEndInWhenClauseFollowedByStatement", + value: "CREATE TRIGGER my_trigger BEFORE INSERT ON my_table WHEN CASE WHEN NEW.id > 0 THEN 1 ELSE 0 END = 1 BEGIN SELECT 1; END; SELECT 2;", + stmts: []string{ + "CREATE TRIGGER my_trigger BEFORE INSERT ON my_table WHEN CASE WHEN NEW.id > 0 THEN 1 ELSE 0 END = 1 BEGIN SELECT 1; END", + "SELECT 2", + }, + extraInfo: generateSimpleSplitStatementExtraInfo(sqliteparser.SQLiteLexerSCOL), + }, { name: "IncompleteCreateTriggerStatement", value: "CREATE TRIGGER update_updated_at AFTER UPDATE ON users FOR EACH ROW BEGIN UPDATE users SET updated_at = 0 WHERE id = NEW.id;",