Ver Fonte

LibSQL: Move Order and Nulls enums from SQL::AST to SQL namespace

The Order enum is used in the Meta component of LibSQL. Using this enum
meant having to include the monster AST/AST.h include file. Furthermore,
they are sort of basic and therefore can live in the general SQL
namespace. Moved to LibSQL/Type.h.

Also introduced a new class, SQLResult, which is needed in future
patches.
Jan de Visser há 4 anos atrás
pai
commit
30691549fd

+ 1 - 1
Tests/LibSQL/TestSqlBtreeIndex.cpp

@@ -127,7 +127,7 @@ void insert_into_and_scan_btree(int num_keys);
 NonnullRefPtr<SQL::BTree> setup_btree(SQL::Heap& heap)
 {
     SQL::TupleDescriptor tuple_descriptor;
-    tuple_descriptor.append({ "key_value", SQL::SQLType::Integer, SQL::AST::Order::Ascending });
+    tuple_descriptor.append({ "key_value", SQL::SQLType::Integer, SQL::Order::Ascending });
 
     auto root_pointer = heap.user_value(0);
     if (!root_pointer) {

+ 2 - 2
Tests/LibSQL/TestSqlHashIndex.cpp

@@ -124,8 +124,8 @@ void insert_into_and_scan_hash_index(int num_keys);
 NonnullRefPtr<SQL::HashIndex> setup_hash_index(SQL::Heap& heap)
 {
     SQL::TupleDescriptor tuple_descriptor;
-    tuple_descriptor.append({ "key_value", SQL::SQLType::Integer, SQL::AST::Order::Ascending });
-    tuple_descriptor.append({ "text_value", SQL::SQLType::Text, SQL::AST::Order::Ascending });
+    tuple_descriptor.append({ "key_value", SQL::SQLType::Integer, SQL::Order::Ascending });
+    tuple_descriptor.append({ "text_value", SQL::SQLType::Text, SQL::Order::Ascending });
 
     auto directory_pointer = heap.user_value(0);
     if (!directory_pointer) {

+ 9 - 9
Tests/LibSQL/TestSqlStatementParser.cpp

@@ -567,8 +567,8 @@ TEST_CASE(select)
 
     struct Ordering {
         String collation_name;
-        SQL::AST::Order order;
-        SQL::AST::Nulls nulls;
+        SQL::Order order;
+        SQL::Nulls nulls;
     };
 
     auto validate = [](StringView sql, Vector<Type> expected_columns, Vector<From> expected_from_list, bool expect_where_clause, size_t expected_group_by_size, bool expect_having_clause, Vector<Ordering> expected_ordering, bool expect_limit_clause, bool expect_offset_clause) {
@@ -674,13 +674,13 @@ TEST_CASE(select)
     validate("SELECT * FROM table_name GROUP BY column1, column2, column3;", all, from, false, 3, false, {}, false, false);
     validate("SELECT * FROM table_name GROUP BY column_name HAVING 'abc';", all, from, false, 1, true, {}, false, false);
 
-    validate("SELECT * FROM table_name ORDER BY column_name;", all, from, false, 0, false, { { {}, SQL::AST::Order::Ascending, SQL::AST::Nulls::First } }, false, false);
-    validate("SELECT * FROM table_name ORDER BY column_name COLLATE collation;", all, from, false, 0, false, { { "COLLATION", SQL::AST::Order::Ascending, SQL::AST::Nulls::First } }, false, false);
-    validate("SELECT * FROM table_name ORDER BY column_name ASC;", all, from, false, 0, false, { { {}, SQL::AST::Order::Ascending, SQL::AST::Nulls::First } }, false, false);
-    validate("SELECT * FROM table_name ORDER BY column_name DESC;", all, from, false, 0, false, { { {}, SQL::AST::Order::Descending, SQL::AST::Nulls::Last } }, false, false);
-    validate("SELECT * FROM table_name ORDER BY column_name ASC NULLS LAST;", all, from, false, 0, false, { { {}, SQL::AST::Order::Ascending, SQL::AST::Nulls::Last } }, false, false);
-    validate("SELECT * FROM table_name ORDER BY column_name DESC NULLS FIRST;", all, from, false, 0, false, { { {}, SQL::AST::Order::Descending, SQL::AST::Nulls::First } }, false, false);
-    validate("SELECT * FROM table_name ORDER BY column1, column2 DESC, column3 NULLS LAST;", all, from, false, 0, false, { { {}, SQL::AST::Order::Ascending, SQL::AST::Nulls::First }, { {}, SQL::AST::Order::Descending, SQL::AST::Nulls::Last }, { {}, SQL::AST::Order::Ascending, SQL::AST::Nulls::Last } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column_name;", all, from, false, 0, false, { { {}, SQL::Order::Ascending, SQL::Nulls::First } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column_name COLLATE collation;", all, from, false, 0, false, { { "COLLATION", SQL::Order::Ascending, SQL::Nulls::First } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column_name ASC;", all, from, false, 0, false, { { {}, SQL::Order::Ascending, SQL::Nulls::First } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column_name DESC;", all, from, false, 0, false, { { {}, SQL::Order::Descending, SQL::Nulls::Last } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column_name ASC NULLS LAST;", all, from, false, 0, false, { { {}, SQL::Order::Ascending, SQL::Nulls::Last } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column_name DESC NULLS FIRST;", all, from, false, 0, false, { { {}, SQL::Order::Descending, SQL::Nulls::First } }, false, false);
+    validate("SELECT * FROM table_name ORDER BY column1, column2 DESC, column3 NULLS LAST;", all, from, false, 0, false, { { {}, SQL::Order::Ascending, SQL::Nulls::First }, { {}, SQL::Order::Descending, SQL::Nulls::Last }, { {}, SQL::Order::Ascending, SQL::Nulls::Last } }, false, false);
 
     validate("SELECT * FROM table_name LIMIT 15;", all, from, false, 0, false, {}, true, false);
     validate("SELECT * FROM table_name LIMIT 15 OFFSET 16;", all, from, false, 0, false, {}, true, true);

+ 8 - 8
Tests/LibSQL/TestSqlValueAndTuple.cpp

@@ -136,8 +136,8 @@ TEST_CASE(order_int_values)
 TEST_CASE(tuple)
 {
     SQL::TupleDescriptor descriptor;
-    descriptor.append({ "col1", SQL::SQLType::Text, SQL::AST::Order::Ascending });
-    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::AST::Order::Descending });
+    descriptor.append({ "col1", SQL::SQLType::Text, SQL::Order::Ascending });
+    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::Order::Descending });
     SQL::Tuple tuple(descriptor);
 
     tuple["col1"] = "Test";
@@ -149,8 +149,8 @@ TEST_CASE(tuple)
 TEST_CASE(serialize_tuple)
 {
     SQL::TupleDescriptor descriptor;
-    descriptor.append({ "col1", SQL::SQLType::Text, SQL::AST::Order::Ascending });
-    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::AST::Order::Descending });
+    descriptor.append({ "col1", SQL::SQLType::Text, SQL::Order::Ascending });
+    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::Order::Descending });
     SQL::Tuple tuple(descriptor);
 
     tuple["col1"] = "Test";
@@ -170,8 +170,8 @@ TEST_CASE(serialize_tuple)
 TEST_CASE(copy_tuple)
 {
     SQL::TupleDescriptor descriptor;
-    descriptor.append({ "col1", SQL::SQLType::Text, SQL::AST::Order::Ascending });
-    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::AST::Order::Descending });
+    descriptor.append({ "col1", SQL::SQLType::Text, SQL::Order::Ascending });
+    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::Order::Descending });
     SQL::Tuple tuple(descriptor);
 
     tuple["col1"] = "Test";
@@ -188,8 +188,8 @@ TEST_CASE(copy_tuple)
 TEST_CASE(compare_tuples)
 {
     SQL::TupleDescriptor descriptor;
-    descriptor.append({ "col1", SQL::SQLType::Text, SQL::AST::Order::Ascending });
-    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::AST::Order::Descending });
+    descriptor.append({ "col1", SQL::SQLType::Text, SQL::Order::Ascending });
+    descriptor.append({ "col2", SQL::SQLType::Integer, SQL::Order::Descending });
 
     SQL::Tuple tuple1(descriptor);
     tuple1["col1"] = "Test";

+ 2 - 10
Userland/Libraries/LibSQL/AST/AST.h

@@ -13,6 +13,8 @@
 #include <AK/String.h>
 #include <LibSQL/AST/Token.h>
 #include <LibSQL/Forward.h>
+#include <LibSQL/SQLResult.h>
+#include <LibSQL/Type.h>
 
 namespace SQL::AST {
 
@@ -251,16 +253,6 @@ private:
     NonnullRefPtrVector<TableOrSubquery> m_subqueries {};
 };
 
-enum class Order {
-    Ascending,
-    Descending,
-};
-
-enum class Nulls {
-    First,
-    Last,
-};
-
 class OrderingTerm : public ASTNode {
 public:
     OrderingTerm(NonnullRefPtr<Expression> expression, String collation_name, Order order, Nulls nulls)

+ 1 - 0
Userland/Libraries/LibSQL/Forward.h

@@ -22,6 +22,7 @@ class IndexDef;
 class Key;
 class KeyPartDef;
 class Row;
+class SQLResult;
 class TableDef;
 class TreeNode;
 class Tuple;

+ 13 - 13
Userland/Libraries/LibSQL/Meta.cpp

@@ -37,7 +37,7 @@ NonnullRefPtr<IndexDef> SchemaDef::index_def()
 {
     NonnullRefPtr<IndexDef> s_index_def = IndexDef::construct("$schema", true, 0);
     if (!s_index_def->size()) {
-        s_index_def->append_column("schema_name", SQLType::Text, AST::Order::Ascending);
+        s_index_def->append_column("schema_name", SQLType::Text, Order::Ascending);
     }
     return s_index_def;
 }
@@ -70,15 +70,15 @@ NonnullRefPtr<IndexDef> ColumnDef::index_def()
 {
     NonnullRefPtr<IndexDef> s_index_def = IndexDef::construct("$column", true, 0);
     if (!s_index_def->size()) {
-        s_index_def->append_column("table_hash", SQLType::Integer, AST::Order::Ascending);
-        s_index_def->append_column("column_number", SQLType::Integer, AST::Order::Ascending);
-        s_index_def->append_column("column_name", SQLType::Text, AST::Order::Ascending);
-        s_index_def->append_column("column_type", SQLType::Integer, AST::Order::Ascending);
+        s_index_def->append_column("table_hash", SQLType::Integer, Order::Ascending);
+        s_index_def->append_column("column_number", SQLType::Integer, Order::Ascending);
+        s_index_def->append_column("column_name", SQLType::Text, Order::Ascending);
+        s_index_def->append_column("column_type", SQLType::Integer, Order::Ascending);
     }
     return s_index_def;
 }
 
-KeyPartDef::KeyPartDef(IndexDef* index, String name, SQLType sql_type, AST::Order sort_order)
+KeyPartDef::KeyPartDef(IndexDef* index, String name, SQLType sql_type, Order sort_order)
     : ColumnDef(index, index->size(), move(name), sql_type)
     , m_sort_order(sort_order)
 {
@@ -96,7 +96,7 @@ IndexDef::IndexDef(String name, bool unique, u32 pointer)
 {
 }
 
-void IndexDef::append_column(String name, SQLType sql_type, AST::Order sort_order)
+void IndexDef::append_column(String name, SQLType sql_type, Order sort_order)
 {
     auto part = KeyPartDef::construct(this, move(name), sql_type, sort_order);
     m_key_definition.append(part);
@@ -131,9 +131,9 @@ NonnullRefPtr<IndexDef> IndexDef::index_def()
 {
     NonnullRefPtr<IndexDef> s_index_def = IndexDef::construct("$index", true, 0);
     if (!s_index_def->size()) {
-        s_index_def->append_column("table_hash", SQLType::Integer, AST::Order::Ascending);
-        s_index_def->append_column("index_name", SQLType::Text, AST::Order::Ascending);
-        s_index_def->append_column("unique", SQLType::Integer, AST::Order::Ascending);
+        s_index_def->append_column("table_hash", SQLType::Integer, Order::Ascending);
+        s_index_def->append_column("index_name", SQLType::Text, Order::Ascending);
+        s_index_def->append_column("unique", SQLType::Integer, Order::Ascending);
     }
     return s_index_def;
 }
@@ -149,7 +149,7 @@ TupleDescriptor TableDef::to_tuple_descriptor() const
 {
     TupleDescriptor ret;
     for (auto& part : m_columns) {
-        ret.append({ part.name(), part.type(), AST::Order::Ascending });
+        ret.append({ part.name(), part.type(), Order::Ascending });
     }
     return ret;
 }
@@ -192,8 +192,8 @@ NonnullRefPtr<IndexDef> TableDef::index_def()
 {
     NonnullRefPtr<IndexDef> s_index_def = IndexDef::construct("$table", true, 0);
     if (!s_index_def->size()) {
-        s_index_def->append_column("schema_hash", SQLType::Integer, AST::Order::Ascending);
-        s_index_def->append_column("table_name", SQLType::Text, AST::Order::Ascending);
+        s_index_def->append_column("schema_hash", SQLType::Integer, Order::Ascending);
+        s_index_def->append_column("table_name", SQLType::Text, Order::Ascending);
     }
     return s_index_def;
 }

+ 4 - 5
Userland/Libraries/LibSQL/Meta.h

@@ -13,7 +13,6 @@
 #include <AK/String.h>
 #include <AK/Vector.h>
 #include <LibCore/Object.h>
-#include <LibSQL/AST/AST.h>
 #include <LibSQL/Forward.h>
 #include <LibSQL/Key.h>
 #include <LibSQL/Type.h>
@@ -90,11 +89,11 @@ class KeyPartDef : public ColumnDef {
     C_OBJECT(KeyPartDef);
 
 public:
-    KeyPartDef(IndexDef*, String, SQLType, AST::Order = AST::Order::Ascending);
-    AST::Order sort_order() const { return m_sort_order; }
+    KeyPartDef(IndexDef*, String, SQLType, Order = Order::Ascending);
+    Order sort_order() const { return m_sort_order; }
 
 private:
-    AST::Order m_sort_order { AST::Order::Ascending };
+    Order m_sort_order { Order::Ascending };
 };
 
 class IndexDef : public Relation {
@@ -106,7 +105,7 @@ public:
     NonnullRefPtrVector<KeyPartDef> key_definition() const { return m_key_definition; }
     bool unique() const { return m_unique; }
     [[nodiscard]] size_t size() const { return m_key_definition.size(); }
-    void append_column(String, SQLType, AST::Order = AST::Order::Ascending);
+    void append_column(String, SQLType, Order = Order::Ascending);
     Key key() const override;
     [[nodiscard]] TupleDescriptor to_tuple_descriptor() const;
     static NonnullRefPtr<IndexDef> index_def();

+ 141 - 0
Userland/Libraries/LibSQL/SQLResult.h

@@ -0,0 +1,141 @@
+/*
+ * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
+ *
+ * SPDX-License-Identifier: BSD-2-Clause
+ */
+
+#pragma once
+
+#include <AK/NonnullOwnPtrVector.h>
+#include <AK/Vector.h>
+#include <LibCore/Object.h>
+#include <LibSQL/Tuple.h>
+#include <LibSQL/Type.h>
+
+namespace SQL {
+
+#define ENUMERATE_SQL_COMMANDS(S) \
+    S(Create)                     \
+    S(Delete)                     \
+    S(Insert)                     \
+    S(Select)                     \
+    S(Update)
+
+enum class SQLCommand {
+#undef __ENUMERATE_SQL_COMMAND
+#define __ENUMERATE_SQL_COMMAND(command) command,
+    ENUMERATE_SQL_COMMANDS(__ENUMERATE_SQL_COMMAND)
+#undef __ENUMERATE_SQL_COMMAND
+};
+
+constexpr char const* command_tag(SQLCommand command)
+{
+    switch (command) {
+#undef __ENUMERATE_SQL_COMMAND
+#define __ENUMERATE_SQL_COMMAND(command) \
+    case SQLCommand::command:            \
+        return #command;
+        ENUMERATE_SQL_COMMANDS(__ENUMERATE_SQL_COMMAND)
+#undef __ENUMERATE_SQL_COMMAND
+    }
+}
+
+#define ENUMERATE_SQL_ERRORS(S)                                 \
+    S(NoError, "No error")                                      \
+    S(DatabaseUnavailable, "Database Unavailable")              \
+    S(StatementUnavailable, "Statement with id {} Unavailable") \
+    S(SyntaxError, "Syntax Error")                              \
+    S(DatabaseDoesNotExist, "Database {} does not exist")       \
+    S(SchemaDoesNotExist, "Schema {} does not exist")           \
+    S(SchemaExists, "Schema {} already exist")                  \
+    S(TableDoesNotExist, "Table {} does not exist")             \
+    S(TableExists, "Table {} already exist")                    \
+    S(InvalidType, "Invalid type {}")
+
+enum class SQLErrorCode {
+#undef __ENUMERATE_SQL_ERROR
+#define __ENUMERATE_SQL_ERROR(error, description) error,
+    ENUMERATE_SQL_ERRORS(__ENUMERATE_SQL_ERROR)
+#undef __ENUMERATE_SQL_ERROR
+};
+
+struct SQLError {
+    SQLErrorCode code { SQLErrorCode::NoError };
+    String error_argument { "" };
+
+    String to_string() const
+    {
+        String code_string;
+        String message;
+        switch (code) {
+#undef __ENUMERATE_SQL_ERROR
+#define __ENUMERATE_SQL_ERROR(error, description) \
+    case SQLErrorCode::error:                     \
+        code_string = #error;                     \
+        message = description;                    \
+        break;
+            ENUMERATE_SQL_ERRORS(__ENUMERATE_SQL_ERROR)
+#undef __ENUMERATE_SQL_ERROR
+        default:
+            VERIFY_NOT_REACHED();
+        }
+        if (!error_argument.is_null() && !error_argument.is_empty()) {
+            if (message.find("{}").has_value()) {
+                message = String::formatted(message, error_argument);
+            } else {
+                message = String::formatted("{}: {}", message, error_argument);
+            }
+        }
+        if (message.is_null() || (message.is_empty())) {
+            return code_string;
+        } else {
+            return String::formatted("{}: {}", code_string, message);
+        }
+    }
+};
+
+class SQLResult : public Core::Object {
+    C_OBJECT(SQLResult)
+
+public:
+    void append(Tuple const& tuple)
+    {
+        m_has_results = true;
+        m_result_set.append(tuple);
+    }
+
+    SQLCommand command() const { return m_command; }
+    int updated() const { return m_update_count; }
+    int inserted() const { return m_insert_count; }
+    int deleted() const { return m_delete_count; }
+    SQLError const& error() const { return m_error; }
+    bool has_results() const { return m_has_results; }
+    Vector<Tuple> const& results() const { return m_result_set; }
+
+private:
+    SQLResult() = default;
+
+    explicit SQLResult(SQLCommand command, int update_count = 0, int insert_count = 0, int delete_count = 0)
+        : m_command(command)
+        , m_update_count(update_count)
+        , m_insert_count(insert_count)
+        , m_delete_count(delete_count)
+    {
+    }
+
+    SQLResult(SQLCommand command, SQLErrorCode error_code, String error_argument)
+        : m_command(command)
+        , m_error({ error_code, move(error_argument) })
+    {
+    }
+
+    SQLCommand m_command { SQLCommand::Select };
+    SQLError m_error { SQLErrorCode::NoError, "" };
+    int m_update_count { 0 };
+    int m_insert_count { 0 };
+    int m_delete_count { 0 };
+    bool m_has_results { false };
+    Vector<Tuple> m_result_set;
+};
+
+}

+ 11 - 2
Userland/Libraries/LibSQL/Tuple.cpp

@@ -174,6 +174,15 @@ String Tuple::to_string() const
     return builder.build();
 }
 
+Vector<String> Tuple::to_string_vector() const
+{
+    Vector<String> ret;
+    for (auto& value : m_data) {
+        ret.append(value.to_string().value());
+    }
+    return ret;
+}
+
 size_t Tuple::size() const
 {
     size_t sz = sizeof(u32);
@@ -203,7 +212,7 @@ int Tuple::compare(const Tuple& other) const
     for (auto ix = 0u; ix < num_values; ix++) {
         auto ret = m_data[ix].compare(other.m_data[ix]);
         if (ret != 0) {
-            if ((ix < m_descriptor.size()) && m_descriptor[ix].order == AST::Order::Descending)
+            if ((ix < m_descriptor.size()) && m_descriptor[ix].order == Order::Descending)
                 ret = -ret;
             return ret;
         }
@@ -223,7 +232,7 @@ int Tuple::match(const Tuple& other) const
             return -1;
         auto ret = m_data[my_index.value()].compare(other_value);
         if (ret != 0)
-            return (m_descriptor[my_index.value()].order == AST::Order::Descending) ? -ret : ret;
+            return (m_descriptor[my_index.value()].order == Order::Descending) ? -ret : ret;
         other_index++;
     }
     return 0;

+ 2 - 0
Userland/Libraries/LibSQL/Tuple.h

@@ -7,6 +7,7 @@
 #pragma once
 
 #include <AK/Debug.h>
+#include <AK/Vector.h>
 #include <LibSQL/Forward.h>
 #include <LibSQL/TupleDescriptor.h>
 #include <LibSQL/Value.h>
@@ -42,6 +43,7 @@ public:
 
     [[nodiscard]] String to_string() const;
     explicit operator String() const { return to_string(); }
+    [[nodiscard]] Vector<String> to_string_vector() const;
 
     bool operator<(Tuple const& other) const { return compare(other) < 0; }
     bool operator<=(Tuple const& other) const { return compare(other) <= 0; }

+ 1 - 2
Userland/Libraries/LibSQL/TupleDescriptor.h

@@ -7,7 +7,6 @@
 #pragma once
 
 #include <AK/Vector.h>
-#include <LibSQL/AST/AST.h>
 #include <LibSQL/Type.h>
 
 namespace SQL {
@@ -15,7 +14,7 @@ namespace SQL {
 struct TupleElement {
     String name { "" };
     SQLType type { SQLType::Text };
-    AST::Order order { AST::Order::Ascending };
+    Order order { Order::Ascending };
 
     bool operator==(TupleElement const&) const = default;
 };

+ 10 - 0
Userland/Libraries/LibSQL/Type.h

@@ -37,4 +37,14 @@ inline static size_t size_of(SQLType t)
     }
 }
 
+enum class Order {
+    Ascending,
+    Descending,
+};
+
+enum class Nulls {
+    First,
+    Last,
+};
+
 }