From d025568f1ae482a326477da6a665a259a6715340 Mon Sep 17 00:00:00 2001 From: Simon Binder Date: Wed, 24 Apr 2024 18:59:10 +0200 Subject: [PATCH] Don't allow aliases for sources in `IN` expression --- sqlparser/CHANGELOG.md | 5 +++ sqlparser/lib/src/reader/parser.dart | 16 +++++---- sqlparser/pubspec.yaml | 2 +- .../test/parser/select/generic_test.dart | 34 +++++++++++++++++++ 4 files changed, 49 insertions(+), 8 deletions(-) diff --git a/sqlparser/CHANGELOG.md b/sqlparser/CHANGELOG.md index b3806d76..6a25c1b3 100644 --- a/sqlparser/CHANGELOG.md +++ b/sqlparser/CHANGELOG.md @@ -1,3 +1,8 @@ +## 0.35.1 + +- Fix `IN` expressions accepting aliases, causing some queries to get parsed + incorrectly. + ## 0.35.0 - Fix parsing binary literals. diff --git a/sqlparser/lib/src/reader/parser.dart b/sqlparser/lib/src/reader/parser.dart index 288d09b9..a6a44aaf 100644 --- a/sqlparser/lib/src/reader/parser.dart +++ b/sqlparser/lib/src/reader/parser.dart @@ -517,7 +517,7 @@ class Parser { } else if (_check(TokenType.leftParen)) { inside = _consumeTuple(orSubQuery: true) as InExpressionTarget; } else { - final target = _tableOrSubquery(); + final target = _tableOrSubquery(allowAlias: false); // TableOrSubquery is either a table reference, a table-valued function, // or a Subquery. We don't support subqueries, but they can't be parsed // here because we would have entered the tuple case above. @@ -1383,18 +1383,18 @@ class Parser { return _joinClause(start) ?? start; } - TableOrSubquery _tableOrSubquery() { + TableOrSubquery _tableOrSubquery({bool allowAlias = true}) { // this is what we're parsing: https://www.sqlite.org/syntax/table-or-subquery.html // we currently only support regular tables, table functions and nested // selects - final tableRef = _tableReferenceOrNull(); + final tableRef = _tableReferenceOrNull(allowAlias: allowAlias); if (tableRef != null) { // this is a bit hacky. If the table reference only consists of one // identifer and it's followed by a (, it's a table-valued function if (tableRef.as == null && _matchOne(TokenType.leftParen)) { final params = _functionParameters(); _consume(TokenType.rightParen, 'Expected closing parenthesis'); - final alias = _as(); + final alias = allowAlias ? _as() : null; return TableValuedFunction(tableRef.tableName, params, as: alias?.identifier) @@ -1408,7 +1408,7 @@ class Parser { _consume(TokenType.rightParen, 'Expected a right bracket to terminate the inner select'); - final alias = _as(); + final alias = allowAlias ? _as() : null; return SelectStatementAsSource( statement: innerStmt, as: alias?.identifier) ..setSpan(first, _previous); @@ -1417,9 +1417,11 @@ class Parser { _error('Expected a table name or a nested select statement'); } - TableReference? _tableReferenceOrNull() { + TableReference? _tableReferenceOrNull({bool allowAlias = true}) { _suggestHint(const TableNameDescription()); - if (_check(TokenType.identifier)) return _tableReference(); + if (_check(TokenType.identifier)) { + return _tableReference(allowAlias: allowAlias); + } return null; } diff --git a/sqlparser/pubspec.yaml b/sqlparser/pubspec.yaml index 271a4321..e8daa32f 100644 --- a/sqlparser/pubspec.yaml +++ b/sqlparser/pubspec.yaml @@ -1,6 +1,6 @@ name: sqlparser description: Parses sqlite statements and performs static analysis on them -version: 0.35.0 +version: 0.35.1 homepage: https://github.com/simolus3/drift/tree/develop/sqlparser repository: https://github.com/simolus3/drift #homepage: https://drift.simonbinder.eu/ diff --git a/sqlparser/test/parser/select/generic_test.dart b/sqlparser/test/parser/select/generic_test.dart index e83f6d96..51f70636 100644 --- a/sqlparser/test/parser/select/generic_test.dart +++ b/sqlparser/test/parser/select/generic_test.dart @@ -54,6 +54,40 @@ final Map testCases = { ], from: TableReference('tbl'), ), + 'SELECT col IN tbl AS in_tbl': SelectStatement(columns: [ + ExpressionResultColumn( + expression: InExpression( + left: Reference(columnName: 'col'), + inside: TableReference('tbl'), + ), + as: 'in_tbl', + ), + ]), + 'SELECT col IN (SELECT 2) AS in_select': SelectStatement(columns: [ + ExpressionResultColumn( + expression: InExpression( + left: Reference(columnName: 'col'), + inside: SubQuery( + select: SelectStatement( + columns: [ExpressionResultColumn(expression: NumericLiteral(2))], + ), + ), + ), + as: 'in_select', + ), + ]), + 'SELECT col IN tbl_valued() AS in_select': SelectStatement(columns: [ + ExpressionResultColumn( + expression: InExpression( + left: Reference(columnName: 'col'), + inside: TableValuedFunction( + 'tbl_valued', + ExprFunctionParameters(parameters: []), + ), + ), + as: 'in_select', + ), + ]), }; void main() {