mirror of
https://github.com/RGBCube/serenity
synced 2025-07-25 21:37:35 +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;
|
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 {
|
class InChainedExpression : public InvertibleNestedExpression {
|
||||||
public:
|
public:
|
||||||
InChainedExpression(NonnullRefPtr<Expression> expression, NonnullRefPtr<ChainedExpression> expression_chain, bool invert_expression)
|
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 (consume_if(TokenType::ParenOpen)) {
|
||||||
if (match(TokenType::Select)) {
|
if (match(TokenType::Select)) {
|
||||||
// FIXME: Parse "select-stmt".
|
auto select_statement = parse_select_statement({});
|
||||||
return {};
|
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
|
// 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);
|
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)
|
TEST_MAIN(SqlExpressionParser)
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue