1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-07-25 22:07:35 +00:00

LibSQL: Parse IN / NOT IN expressions with a nested SELECT statement

This commit is contained in:
Timothy Flynn 2021-04-23 14:54:37 -04:00 committed by Andreas Kling
parent 004025c3c4
commit fa59d02692
3 changed files with 39 additions and 2 deletions

View file

@ -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)

View file

@ -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

View file

@ -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)