Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion go/vt/sqlparser/ast.go
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,16 @@ func ParseStrictDDL(sql string) (Statement, error) {
// the next call to ParseNext to parse any subsequent SQL statements. When
// there are no more statements to parse, a error of io.EOF is returned.
func ParseNext(tokenizer *Tokenizer) (Statement, error) {
return parseNext(tokenizer, false)
}

// ParseNextStrictDDL is the same as ParseNext except it errors on
// partially parsed DDL statements.
func ParseNextStrictDDL(tokenizer *Tokenizer) (Statement, error) {
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for the change. Could you also add a test for this functionality?

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

whoops, yes, added a test. Thanks!

return parseNext(tokenizer, true)
}

func parseNext(tokenizer *Tokenizer, strict bool) (Statement, error) {
if tokenizer.lastChar == ';' {
tokenizer.next()
tokenizer.skipBlank()
Expand All @@ -88,7 +98,7 @@ func ParseNext(tokenizer *Tokenizer) (Statement, error) {
tokenizer.reset()
tokenizer.multi = true
if yyParse(tokenizer) != 0 {
if tokenizer.partialDDL != nil {
if tokenizer.partialDDL != nil && !strict {
tokenizer.ParseTree = tokenizer.partialDDL
return tokenizer.ParseTree, nil
}
Expand Down
33 changes: 33 additions & 0 deletions go/vt/sqlparser/parse_next_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -161,3 +161,36 @@ func TestParseNextEdgeCases(t *testing.T) {
}
}
}

// TestParseNextEdgeCases tests various ParseNext edge cases.
func TestParseNextStrictNonStrict(t *testing.T) {
// This is one of the edge cases above.
input := "create table a ignore me this is garbage; select 1 from a"
want := []string{"create table a", "select 1 from a"}

// First go through as expected with non-strict DDL parsing.
tokens := NewStringTokenizer(input)
for i, want := range want {
tree, err := ParseNext(tokens)
if err != nil {
t.Fatalf("[%d] ParseNext(%q) err = %q, want nil", i, input, err)
}
if got := String(tree); got != want {
t.Fatalf("[%d] ParseNext(%q) = %q, want %q", i, input, got, want)
}
}

// Now try again with strict parsing and observe the expected error.
tokens = NewStringTokenizer(input)
tree, err := ParseNextStrictDDL(tokens)
if err == nil || !strings.Contains(err.Error(), "ignore") {
t.Fatalf("ParseNext(%q) err = %q, want nil", input, err)
}
tree, err = ParseNextStrictDDL(tokens)
if err != nil {
t.Fatalf("ParseNext(%q) err = %q, want nil", input, err)
}
if got := String(tree); got != want[1] {
t.Fatalf("ParseNext(%q) = %q, want %q", input, got, want)
}
}