diff options
author | Timothy Flynn <trflynn89@pm.me> | 2021-04-23 13:37:47 -0400 |
---|---|---|
committer | Andreas Kling <kling@serenityos.org> | 2021-04-23 22:36:07 +0200 |
commit | cb943a2179cd8e33983eb086e05def3e3e60bc28 (patch) | |
tree | 44ccce936627ba06ad8014c67fcc5600e28371fc | |
parent | 99b38aa3fab3ee545d8467aff3b64565092d497e (diff) | |
download | serenity-cb943a2179cd8e33983eb086e05def3e3e60bc28.zip |
LibSQL: Parse CREATE TABLE statements with a nested SELECT statement
-rw-r--r-- | Userland/Libraries/LibSQL/AST.h | 16 | ||||
-rw-r--r-- | Userland/Libraries/LibSQL/Parser.cpp | 5 | ||||
-rw-r--r-- | Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp | 13 |
3 files changed, 33 insertions, 1 deletions
diff --git a/Userland/Libraries/LibSQL/AST.h b/Userland/Libraries/LibSQL/AST.h index 96f0e970dc..fe8ff4d443 100644 --- a/Userland/Libraries/LibSQL/AST.h +++ b/Userland/Libraries/LibSQL/AST.h @@ -664,6 +664,15 @@ class ErrorStatement final : public Statement { class CreateTable : public Statement { public: + CreateTable(String schema_name, String table_name, RefPtr<Select> select_statement, bool is_temporary, bool is_error_if_table_exists) + : m_schema_name(move(schema_name)) + , m_table_name(move(table_name)) + , m_select_statement(move(select_statement)) + , m_is_temporary(is_temporary) + , m_is_error_if_table_exists(is_error_if_table_exists) + { + } + CreateTable(String schema_name, String table_name, NonnullRefPtrVector<ColumnDefinition> columns, bool is_temporary, bool is_error_if_table_exists) : m_schema_name(move(schema_name)) , m_table_name(move(table_name)) @@ -675,13 +684,20 @@ public: const String& schema_name() const { return m_schema_name; } const String& table_name() const { return m_table_name; } + + bool has_selection() const { return !m_select_statement.is_null(); } + const RefPtr<Select>& select_statement() const { return m_select_statement; } + + bool has_columns() const { return !m_columns.is_empty(); } const NonnullRefPtrVector<ColumnDefinition> columns() const { return m_columns; } + bool is_temporary() const { return m_is_temporary; } bool is_error_if_table_exists() const { return m_is_error_if_table_exists; } private: String m_schema_name; String m_table_name; + RefPtr<Select> m_select_statement; NonnullRefPtrVector<ColumnDefinition> m_columns; bool m_is_temporary; bool m_is_error_if_table_exists; diff --git a/Userland/Libraries/LibSQL/Parser.cpp b/Userland/Libraries/LibSQL/Parser.cpp index 8775c2d3b3..d1a7afda43 100644 --- a/Userland/Libraries/LibSQL/Parser.cpp +++ b/Userland/Libraries/LibSQL/Parser.cpp @@ -81,7 +81,10 @@ NonnullRefPtr<CreateTable> Parser::parse_create_table_statement() String table_name; parse_schema_and_table_name(schema_name, table_name); - // FIXME: Parse "AS select-stmt". + if (consume_if(TokenType::As)) { + auto select_statement = parse_select_statement({}); + return create_ast_node<CreateTable>(move(schema_name), move(table_name), move(select_statement), is_temporary, is_error_if_table_exists); + } NonnullRefPtrVector<ColumnDefinition> column_definitions; parse_comma_separated_list(true, [&]() { column_definitions.append(parse_column_definition()); }); diff --git a/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp b/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp index 7de8e45ed2..06b4b5f82d 100644 --- a/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp +++ b/Userland/Libraries/LibSQL/Tests/TestSqlStatementParser.cpp @@ -45,6 +45,8 @@ TEST_CASE(create_table) EXPECT(parse("CREATE TABLE test ( column1 )").is_error()); EXPECT(parse("CREATE TABLE IF test ( column1 );").is_error()); EXPECT(parse("CREATE TABLE IF NOT test ( column1 );").is_error()); + EXPECT(parse("CREATE TABLE AS;").is_error()); + EXPECT(parse("CREATE TABLE AS SELECT;").is_error()); EXPECT(parse("CREATE TABLE test ( column1 varchar()").is_error()); EXPECT(parse("CREATE TABLE test ( column1 varchar(abc)").is_error()); EXPECT(parse("CREATE TABLE test ( column1 varchar(123 )").is_error()); @@ -55,6 +57,8 @@ TEST_CASE(create_table) EXPECT(parse("CREATE TABLE test ( column1 varchar(0x) )").is_error()); EXPECT(parse("CREATE TABLE test ( column1 varchar(0xzzz) )").is_error()); EXPECT(parse("WITH table AS () CREATE TABLE test ( column1 );").is_error()); + EXPECT(parse("CREATE TABLE test ( column1 int ) AS SELECT * FROM table;").is_error()); + EXPECT(parse("CREATE TABLE test AS SELECT * FROM table ( column1 int ) ;").is_error()); struct Column { StringView name; @@ -75,6 +79,13 @@ TEST_CASE(create_table) EXPECT_EQ(table.is_temporary(), expected_is_temporary); EXPECT_EQ(table.is_error_if_table_exists(), expected_is_error_if_table_exists); + bool expect_select_statement = expected_columns.is_empty(); + EXPECT_EQ(table.has_selection(), expect_select_statement); + EXPECT_EQ(table.has_columns(), !expect_select_statement); + + const auto& select_statement = table.select_statement(); + EXPECT_EQ(select_statement.is_null(), !expect_select_statement); + const auto& columns = table.columns(); EXPECT_EQ(columns.size(), expected_columns.size()); @@ -103,6 +114,8 @@ TEST_CASE(create_table) validate("CREATE TEMPORARY TABLE test ( column1 );", {}, "test", { { "column1", "BLOB" } }, true, true); validate("CREATE TABLE IF NOT EXISTS test ( column1 );", {}, "test", { { "column1", "BLOB" } }, false, false); + validate("CREATE TABLE test AS SELECT * FROM table;", {}, "test", {}); + validate("CREATE TABLE test ( column1 int );", {}, "test", { { "column1", "int" } }); validate("CREATE TABLE test ( column1 varchar );", {}, "test", { { "column1", "varchar" } }); validate("CREATE TABLE test ( column1 varchar(255) );", {}, "test", { { "column1", "varchar", { 255 } } }); |