mirror of https://github.com/AMT-Cheif/drift.git
Support WITH clause for inner select statements
This commit is contained in:
parent
bf1e174ca3
commit
591e1b2bff
|
@ -3,7 +3,7 @@ part of '../ast.dart';
|
|||
/// A subquery, which is an expression. It is expected that the inner query
|
||||
/// only returns one column and one row.
|
||||
class SubQuery extends Expression {
|
||||
final SelectStatement select;
|
||||
final BaseSelectStatement select;
|
||||
|
||||
SubQuery({this.select});
|
||||
|
||||
|
@ -18,7 +18,7 @@ class SubQuery extends Expression {
|
|||
}
|
||||
|
||||
class ExistsExpression extends Expression {
|
||||
final SelectStatement select;
|
||||
final BaseSelectStatement select;
|
||||
|
||||
ExistsExpression({@required this.select});
|
||||
|
||||
|
|
|
@ -66,11 +66,8 @@ mixin CrudParser on ParserBase {
|
|||
..withToken = withToken;
|
||||
}
|
||||
|
||||
/// Parses a select statement as defined in [the sqlite documentation][s-d],
|
||||
/// which means that compound selects and a with clause is supported.
|
||||
///
|
||||
/// [s-d]: https://sqlite.org/syntax/select-stmt.html
|
||||
BaseSelectStatement _defaultSelect() {
|
||||
@override
|
||||
BaseSelectStatement _fullSelect() {
|
||||
final clause = _withClause();
|
||||
return select(withClause: clause);
|
||||
}
|
||||
|
@ -82,6 +79,17 @@ mixin CrudParser on ParserBase {
|
|||
} else {
|
||||
final firstTokenOfBase = _peek;
|
||||
final first = _selectNoCompound(withClause);
|
||||
|
||||
if (first == null) {
|
||||
// _selectNoCompound returns null if there's no select statement at the
|
||||
// current position. That's fine if we didn't encounter an with clause
|
||||
// already
|
||||
if (withClause != null) {
|
||||
_error('Expected a SELECT statement to follow the WITH clause here');
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
final parts = <CompoundSelectPart>[];
|
||||
|
||||
while (true) {
|
||||
|
@ -631,7 +639,7 @@ mixin CrudParser on ParserBase {
|
|||
return const DefaultValues();
|
||||
} else {
|
||||
return SelectInsertSource(
|
||||
_defaultSelect() ?? _error('Expeced a select statement'));
|
||||
_fullSelect() ?? _error('Expeced a select statement'));
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -194,7 +194,7 @@ mixin ExpressionParser on ParserBase {
|
|||
final existsToken = _previous;
|
||||
_consume(
|
||||
TokenType.leftParen, 'Expected opening parenthesis after EXISTS');
|
||||
final selectStmt = select(noCompound: true) as SelectStatement;
|
||||
final selectStmt = _fullSelect() ?? _error('Expected a select statement');
|
||||
_consume(TokenType.rightParen,
|
||||
'Expected closing paranthesis to finish EXISTS expression');
|
||||
return ExistsExpression(select: selectStmt)
|
||||
|
@ -263,7 +263,9 @@ mixin ExpressionParser on ParserBase {
|
|||
|
||||
if (_matchOne(TokenType.leftParen)) {
|
||||
final left = _previous;
|
||||
if (_peek.type == TokenType.select) {
|
||||
|
||||
final selectStmt = _fullSelect(); // returns null if there's no select
|
||||
if (selectStmt != null) {
|
||||
final stmt = select(noCompound: true) as SelectStatement;
|
||||
_consume(TokenType.rightParen, 'Expected a closing bracket');
|
||||
return SubQuery(select: stmt)..setSpan(left, _previous);
|
||||
|
@ -380,7 +382,7 @@ mixin ExpressionParser on ParserBase {
|
|||
_consume(TokenType.leftParen, 'Expected opening parenthesis for tuple');
|
||||
final expressions = <Expression>[];
|
||||
|
||||
final subQuery = select(noCompound: true) as SelectStatement;
|
||||
final subQuery = _fullSelect();
|
||||
if (subQuery == null) {
|
||||
// no sub query found. read expressions that form the tuple.
|
||||
// tuples can be empty `()`, so only start parsing values when it's not
|
||||
|
|
|
@ -169,10 +169,19 @@ abstract class ParserBase {
|
|||
/// [CompoundSelectStatement]. If [noCompound] is set to true, the parser will
|
||||
/// only attempt to parse a [SelectStatement].
|
||||
///
|
||||
/// This method doesn't parse WITH clauses, most users would probably want to
|
||||
/// use [_fullSelect] instead.
|
||||
///
|
||||
/// See also:
|
||||
/// https://www.sqlite.org/lang_select.html
|
||||
BaseSelectStatement select({bool noCompound});
|
||||
|
||||
/// Parses a select statement as defined in [the sqlite documentation][s-d],
|
||||
/// which means that compound selects and a with clause is supported.
|
||||
///
|
||||
/// [s-d]: https://sqlite.org/syntax/select-stmt.html
|
||||
BaseSelectStatement _fullSelect();
|
||||
|
||||
Literal _literalOrNull();
|
||||
OrderingMode _orderingModeOrNull();
|
||||
|
||||
|
|
Loading…
Reference in New Issue