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.
This commit is contained in:
Jan de Visser 2021-06-27 21:00:08 -04:00 committed by Ali Mohammad Pur
parent 633dc74606
commit 30691549fd
Notes: sideshowbarker 2024-07-18 10:04:43 +09:00
13 changed files with 205 additions and 52 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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