diff --git a/sqlparser/lib/src/ast/expressions/simple.dart b/sqlparser/lib/src/ast/expressions/simple.dart index 52b6bc37..0a0f4446 100644 --- a/sqlparser/lib/src/ast/expressions/simple.dart +++ b/sqlparser/lib/src/ast/expressions/simple.dart @@ -128,7 +128,9 @@ class Parentheses extends Expression { final Expression expression; final Token closingRight; - Parentheses(this.openingLeft, this.expression, this.closingRight); + Parentheses(this.openingLeft, this.expression, this.closingRight) { + setSpan(openingLeft, closingRight); + } @override T accept(AstVisitor visitor) { diff --git a/sqlparser/lib/src/reader/parser/parser.dart b/sqlparser/lib/src/reader/parser/parser.dart index 1fddcb11..a6ef51e2 100644 --- a/sqlparser/lib/src/reader/parser/parser.dart +++ b/sqlparser/lib/src/reader/parser/parser.dart @@ -687,6 +687,12 @@ class Parser { _consume(TokenType.rightParen, 'Expected a closing bracket'); return SubQuery(select: stmt); } else { + // alright, it's either a tuple or just parenthesis. A tuple can be + // empty, so if the next statement is the closing bracket we're done + if (_matchOne(TokenType.rightParen)) { + return TupleExpression(expressions: [])..setSpan(left, _previous); + } + final expr = expression(); // Are we witnessing a tuple? diff --git a/sqlparser/test/parser/select/generic_test.dart b/sqlparser/test/parser/select/generic_test.dart index 61537b00..e175f1c5 100644 --- a/sqlparser/test/parser/select/generic_test.dart +++ b/sqlparser/test/parser/select/generic_test.dart @@ -1,66 +1,53 @@ import 'package:sqlparser/src/ast/ast.dart'; -import 'package:sqlparser/src/reader/parser/parser.dart'; -import 'package:sqlparser/src/reader/tokenizer/scanner.dart'; -import 'package:sqlparser/src/reader/tokenizer/token.dart'; -import 'package:sqlparser/src/utils/ast_equality.dart'; -import 'package:test/test.dart'; - import '../utils.dart'; -void main() { - test('parses select statements', () { - final scanner = Scanner( - 'SELECT table.*, *, 1 as name WHERE 1 ORDER BY name LIMIT 3 OFFSET 5'); - final tokens = scanner.scanTokens(); - final parser = Parser(tokens); - - final stmt = parser.select(); - enforceEqual( - stmt, +final Map testCases = { + 'SELECT table.*, *, 1 as name WHERE 1 ORDER BY name LIMIT 3 OFFSET 5': SelectStatement( - columns: [ - StarResultColumn('table'), - StarResultColumn(null), - ExpressionResultColumn( - expression: NumericLiteral(1, token(TokenType.numberLiteral)), - as: 'name', + columns: [ + StarResultColumn('table'), + StarResultColumn(null), + ExpressionResultColumn( + expression: NumericLiteral(1, token(TokenType.numberLiteral)), + as: 'name', + ), + ], + where: NumericLiteral(1, token(TokenType.numberLiteral)), + orderBy: OrderBy(terms: [ + OrderingTerm(expression: Reference(columnName: 'name')), + ]), + limit: Limit( + count: NumericLiteral(3, token(TokenType.numberLiteral)), + offsetSeparator: token(TokenType.offset), + offset: NumericLiteral(5, token(TokenType.numberLiteral)), + ), + ), + 'SELECT table.*, (SELECT * FROM table2) FROM table': SelectStatement( + columns: [ + StarResultColumn('table'), + ExpressionResultColumn( + expression: SubQuery( + select: SelectStatement( + columns: [StarResultColumn(null)], + from: [TableReference('table2', null)], ), - ], - where: NumericLiteral(1, token(TokenType.numberLiteral)), - orderBy: OrderBy(terms: [ - OrderingTerm(expression: Reference(columnName: 'name')), - ]), - limit: Limit( - count: NumericLiteral(3, token(TokenType.numberLiteral)), - offsetSeparator: token(TokenType.offset), - offset: NumericLiteral(5, token(TokenType.numberLiteral)), ), ), - ); - }); + ], + from: [ + TableReference('table', null), + ], + ), + 'SELECT * FROM table WHERE id IN ()': SelectStatement( + columns: [StarResultColumn(null)], + from: [TableReference('table', null)], + where: InExpression( + left: Reference(columnName: 'id'), + inside: TupleExpression(expressions: []), + ), + ), +}; - test('supports subqueries', () { - final scanner = - Scanner('SELECT table.*, (SELECT * FROM table2) FROM table'); - final tokens = scanner.scanTokens(); - final parser = Parser(tokens); - - final stmt = parser.select(); - enforceEqual( - stmt, - SelectStatement(columns: [ - StarResultColumn('table'), - ExpressionResultColumn( - expression: SubQuery( - select: SelectStatement( - columns: [StarResultColumn(null)], - from: [TableReference('table2', null)], - ), - ), - ), - ], from: [ - TableReference('table', null), - ]), - ); - }); +void main() { + testAll(testCases); }