mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:47:46 +00:00
LibSQL: Parse IN / NOT IN expressions with a nested SELECT statement
This commit is contained in:
parent
004025c3c4
commit
fa59d02692
3 changed files with 39 additions and 2 deletions
|
@ -624,6 +624,20 @@ private:
|
|||
NonnullRefPtr<Expression> m_expression;
|
||||
};
|
||||
|
||||
class InSelectionExpression : public InvertibleNestedExpression {
|
||||
public:
|
||||
InSelectionExpression(NonnullRefPtr<Expression> expression, NonnullRefPtr<Select> select_statement, bool invert_expression)
|
||||
: InvertibleNestedExpression(move(expression), invert_expression)
|
||||
, m_select_statement(move(select_statement))
|
||||
{
|
||||
}
|
||||
|
||||
const NonnullRefPtr<Select>& select_statement() const { return m_select_statement; }
|
||||
|
||||
private:
|
||||
NonnullRefPtr<Select> m_select_statement;
|
||||
};
|
||||
|
||||
class InChainedExpression : public InvertibleNestedExpression {
|
||||
public:
|
||||
InChainedExpression(NonnullRefPtr<Expression> expression, NonnullRefPtr<ChainedExpression> expression_chain, bool invert_expression)
|
||||
|
|
|
@ -628,8 +628,8 @@ Optional<NonnullRefPtr<Expression>> Parser::parse_in_expression(NonnullRefPtr<Ex
|
|||
|
||||
if (consume_if(TokenType::ParenOpen)) {
|
||||
if (match(TokenType::Select)) {
|
||||
// FIXME: Parse "select-stmt".
|
||||
return {};
|
||||
auto select_statement = parse_select_statement({});
|
||||
return create_ast_node<InSelectionExpression>(move(expression), move(select_statement), invert_expression);
|
||||
}
|
||||
|
||||
// FIXME: Consolidate this with parse_chained_expression(). That method consumes the opening paren as
|
||||
|
|
|
@ -580,4 +580,27 @@ TEST_CASE(in_chained_expression)
|
|||
validate("15 NOT IN (15, 16)", 2, true);
|
||||
}
|
||||
|
||||
TEST_CASE(in_selection_expression)
|
||||
{
|
||||
EXPECT(parse("IN (SELECT)").is_error());
|
||||
EXPECT(parse("IN (SELECT * FROM table, SELECT * FROM table);").is_error());
|
||||
EXPECT(parse("NOT IN (SELECT)").is_error());
|
||||
EXPECT(parse("NOT IN (SELECT * FROM table, SELECT * FROM table);").is_error());
|
||||
|
||||
auto validate = [](StringView sql, bool expected_invert_expression) {
|
||||
auto result = parse(sql);
|
||||
EXPECT(!result.is_error());
|
||||
|
||||
auto expression = result.release_value();
|
||||
EXPECT(is<SQL::InSelectionExpression>(*expression));
|
||||
|
||||
const auto& in = static_cast<const SQL::InSelectionExpression&>(*expression);
|
||||
EXPECT(!is<SQL::ErrorExpression>(*in.expression()));
|
||||
EXPECT_EQ(in.invert_expression(), expected_invert_expression);
|
||||
};
|
||||
|
||||
validate("15 IN (SELECT * FROM table)", false);
|
||||
validate("15 NOT IN (SELECT * FROM table)", true);
|
||||
}
|
||||
|
||||
TEST_MAIN(SqlExpressionParser)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue