From 2af417d5c259f7301174e8444177035769dacd95 Mon Sep 17 00:00:00 2001 From: Seebs Date: Mon, 3 Apr 2023 13:51:50 -0500 Subject: [PATCH] don't panic on a MIN that isn't a call parseOperand was assuming that any reference to MIN in a place where an operand was expected was a call, which it should be, but it might not be. parseCallExpression panics if it doesn't find a parenthesis, because it's never supposed to be called when we don't know we have one. The test for this is in with MinMaxColumnConstraints, even though it's actually a test of MinMaxFunctionCalls, because that's where the other tests involving the special MIN/MAX tokens live. We also stop checking whether MIN or MAX might actually be QIDENT. If you use a quoted identifier, we're over in the QIDENT case, not the MIN/MAX case. If the token was MIN or MAX, it's always unquoted. --- sql3/parser/parser.go | 8 ++++++-- sql3/parser/parser_test.go | 3 +++ 2 files changed, 9 insertions(+), 2 deletions(-) diff --git a/sql3/parser/parser.go b/sql3/parser/parser.go index fe8ebea15..3a8ff4e65 100644 --- a/sql3/parser/parser.go +++ b/sql3/parser/parser.go @@ -2742,8 +2742,12 @@ func (p *Parser) parseOperand() (expr Expr, err error) { case VARIABLE: return &Variable{Name: lit, NamePos: pos}, nil case MIN, MAX: - ident := &Ident{Name: lit, NamePos: pos, Quoted: tok == QIDENT} - return p.parseCall(ident) + pk := p.peek() + if pk == LP { + ident := &Ident{Name: lit, NamePos: pos, Quoted: false} + return p.parseCall(ident) + } + return nil, p.errorExpected(p.pos, pk, "call expression") case STRING: return &StringLit{ValuePos: pos, Value: lit}, nil case FLOAT: diff --git a/sql3/parser/parser_test.go b/sql3/parser/parser_test.go index deb53a5f9..f548692b9 100644 --- a/sql3/parser/parser_test.go +++ b/sql3/parser/parser_test.go @@ -40,6 +40,9 @@ func TestParser_ParseMinMaxColumnConstraints(t *testing.T) { t.Run("ErrNoKey", func(t *testing.T) { AssertParseStatementError(t, `CREATE TABLE tbl (col1 INT MIN`, `1:30: expected expression, found 'EOF'`) }) + t.Run("ErrNoCall", func(t *testing.T) { + AssertParseStatementError(t, `SELECT MIN;`, `1:11: expected call expression, found ';'`) + }) t.Run("Simple", func(t *testing.T) { AssertParseStatement(t, `CREATE TABLE tbl (col1 INT MIN 0)`, &parser.CreateTableStatement{ Create: pos(0),