From 41e0e4cdd7377fb2df71903a0a0466a26a288eca Mon Sep 17 00:00:00 2001 From: Timothy Flynn Date: Sat, 31 Dec 2022 09:28:09 -0500 Subject: [PATCH] LibSQL: Add parsing and evaluation of BOOLEAN type literals This allows you to enter TRUE or FALSE in a SQL statement for BOOLEAN types. Note that this differs from SQLite, which requires entering 1 or 0 for BOOLEANs; having explicit keywords feels a bit more natural. --- Tests/LibSQL/TestSqlExpressionParser.cpp | 17 +++++++++++++++++ Userland/Libraries/LibSQL/AST/AST.h | 15 +++++++++++++++ Userland/Libraries/LibSQL/AST/Expression.cpp | 5 +++++ Userland/Libraries/LibSQL/AST/Parser.cpp | 4 ++++ Userland/Libraries/LibSQL/AST/Token.h | 2 ++ 5 files changed, 43 insertions(+) diff --git a/Tests/LibSQL/TestSqlExpressionParser.cpp b/Tests/LibSQL/TestSqlExpressionParser.cpp index f308e3fc58..fdba83f651 100644 --- a/Tests/LibSQL/TestSqlExpressionParser.cpp +++ b/Tests/LibSQL/TestSqlExpressionParser.cpp @@ -118,6 +118,23 @@ TEST_CASE(blob_literal) validate("x'DEADC0DE'"sv, "DEADC0DE"sv); } +TEST_CASE(boolean_literal) +{ + auto validate = [](StringView sql, bool expected_value) { + auto result = parse(sql); + EXPECT(!result.is_error()); + + auto expression = result.release_value(); + EXPECT(is(*expression)); + + auto const& literal = static_cast(*expression); + EXPECT_EQ(literal.value(), expected_value); + }; + + validate("TRUE"sv, true); + validate("FALSE"sv, false); +} + TEST_CASE(null_literal) { auto validate = [](StringView sql) { diff --git a/Userland/Libraries/LibSQL/AST/AST.h b/Userland/Libraries/LibSQL/AST/AST.h index fd319289de..c9f5ac20bf 100644 --- a/Userland/Libraries/LibSQL/AST/AST.h +++ b/Userland/Libraries/LibSQL/AST/AST.h @@ -357,6 +357,21 @@ private: DeprecatedString m_value; }; +class BooleanLiteral : public Expression { +public: + explicit BooleanLiteral(bool value) + : m_value(value) + { + } + + bool value() const { return m_value; } + + virtual ResultOr evaluate(ExecutionContext&) const override; + +private: + bool m_value { false }; +}; + class NullLiteral : public Expression { public: virtual ResultOr evaluate(ExecutionContext&) const override; diff --git a/Userland/Libraries/LibSQL/AST/Expression.cpp b/Userland/Libraries/LibSQL/AST/Expression.cpp index f2506d6e5d..cd2270577d 100644 --- a/Userland/Libraries/LibSQL/AST/Expression.cpp +++ b/Userland/Libraries/LibSQL/AST/Expression.cpp @@ -24,6 +24,11 @@ ResultOr StringLiteral::evaluate(ExecutionContext&) const return Value { value() }; } +ResultOr BooleanLiteral::evaluate(ExecutionContext&) const +{ + return Value { value() }; +} + ResultOr NullLiteral::evaluate(ExecutionContext&) const { return Value {}; diff --git a/Userland/Libraries/LibSQL/AST/Parser.cpp b/Userland/Libraries/LibSQL/AST/Parser.cpp index 81ef007519..7d91cc85e2 100644 --- a/Userland/Libraries/LibSQL/AST/Parser.cpp +++ b/Userland/Libraries/LibSQL/AST/Parser.cpp @@ -524,6 +524,10 @@ RefPtr Parser::parse_literal_value_expression() auto value = consume().value(); return create_ast_node(value); } + if (consume_if(TokenType::True)) + return create_ast_node(true); + if (consume_if(TokenType::False)) + return create_ast_node(false); if (consume_if(TokenType::Null)) return create_ast_node(); diff --git a/Userland/Libraries/LibSQL/AST/Token.h b/Userland/Libraries/LibSQL/AST/Token.h index 354f1bdcec..59b889ab0a 100644 --- a/Userland/Libraries/LibSQL/AST/Token.h +++ b/Userland/Libraries/LibSQL/AST/Token.h @@ -69,6 +69,7 @@ namespace SQL::AST { __ENUMERATE_SQL_TOKEN("EXISTS", Exists, Keyword) \ __ENUMERATE_SQL_TOKEN("EXPLAIN", Explain, Keyword) \ __ENUMERATE_SQL_TOKEN("FAIL", Fail, Keyword) \ + __ENUMERATE_SQL_TOKEN("FALSE", False, Keyword) \ __ENUMERATE_SQL_TOKEN("FILTER", Filter, Keyword) \ __ENUMERATE_SQL_TOKEN("FIRST", First, Keyword) \ __ENUMERATE_SQL_TOKEN("FOLLOWING", Following, Keyword) \ @@ -151,6 +152,7 @@ namespace SQL::AST { __ENUMERATE_SQL_TOKEN("TO", To, Keyword) \ __ENUMERATE_SQL_TOKEN("TRANSACTION", Transaction, Keyword) \ __ENUMERATE_SQL_TOKEN("TRIGGER", Trigger, Keyword) \ + __ENUMERATE_SQL_TOKEN("TRUE", True, Keyword) \ __ENUMERATE_SQL_TOKEN("UNBOUNDED", Unbounded, Keyword) \ __ENUMERATE_SQL_TOKEN("UNION", Union, Keyword) \ __ENUMERATE_SQL_TOKEN("UNIQUE", Unique, Keyword) \