Serenity Operating System
at master 133 lines 5.2 kB view raw
1/* 2 * Copyright (c) 2021, Jan de Visser <jan@de-visser.net> 3 * Copyright (c) 2021, Mahmoud Mandour <ma.mandourr@gmail.com> 4 * 5 * SPDX-License-Identifier: BSD-2-Clause 6 */ 7 8#pragma once 9 10#include <AK/Error.h> 11#include <AK/Noncopyable.h> 12#include <LibSQL/Type.h> 13 14namespace SQL { 15 16#define ENUMERATE_SQL_COMMANDS(S) \ 17 S(Unknown) \ 18 S(Create) \ 19 S(Delete) \ 20 S(Describe) \ 21 S(Insert) \ 22 S(Select) \ 23 S(Update) 24 25enum class SQLCommand { 26#undef __ENUMERATE_SQL_COMMAND 27#define __ENUMERATE_SQL_COMMAND(command) command, 28 ENUMERATE_SQL_COMMANDS(__ENUMERATE_SQL_COMMAND) 29#undef __ENUMERATE_SQL_COMMAND 30}; 31 32constexpr char const* command_tag(SQLCommand command) 33{ 34 switch (command) { 35#undef __ENUMERATE_SQL_COMMAND 36#define __ENUMERATE_SQL_COMMAND(command) \ 37 case SQLCommand::command: \ 38 return #command; 39 ENUMERATE_SQL_COMMANDS(__ENUMERATE_SQL_COMMAND) 40#undef __ENUMERATE_SQL_COMMAND 41 } 42} 43 44#define ENUMERATE_SQL_ERRORS(S) \ 45 S(AmbiguousColumnName, "Column name '{}' is ambiguous") \ 46 S(BooleanOperatorTypeMismatch, "Cannot apply '{}' operator to non-boolean operands") \ 47 S(ColumnDoesNotExist, "Column '{}' does not exist") \ 48 S(DatabaseDoesNotExist, "Database '{}' does not exist") \ 49 S(DatabaseUnavailable, "Database Unavailable") \ 50 S(IntegerOperatorTypeMismatch, "Cannot apply '{}' operator to non-numeric operands") \ 51 S(IntegerOverflow, "Operation would cause integer overflow") \ 52 S(InternalError, "{}") \ 53 S(InvalidDatabaseName, "Invalid database name '{}'") \ 54 S(InvalidNumberOfPlaceholderValues, "Number of values does not match number of placeholders") \ 55 S(InvalidNumberOfValues, "Number of values does not match number of columns") \ 56 S(InvalidOperator, "Invalid operator '{}'") \ 57 S(InvalidType, "Invalid type '{}'") \ 58 S(InvalidValueType, "Invalid type for attribute '{}'") \ 59 S(NoError, "No error") \ 60 S(NotYetImplemented, "{}") \ 61 S(NumericOperatorTypeMismatch, "Cannot apply '{}' operator to non-numeric operands") \ 62 S(SchemaDoesNotExist, "Schema '{}' does not exist") \ 63 S(SchemaExists, "Schema '{}' already exist") \ 64 S(StatementUnavailable, "Statement with id '{}' Unavailable") \ 65 S(SyntaxError, "Syntax Error") \ 66 S(TableDoesNotExist, "Table '{}' does not exist") \ 67 S(TableExists, "Table '{}' already exist") 68 69enum class SQLErrorCode { 70#undef __ENUMERATE_SQL_ERROR 71#define __ENUMERATE_SQL_ERROR(error, description) error, 72 ENUMERATE_SQL_ERRORS(__ENUMERATE_SQL_ERROR) 73#undef __ENUMERATE_SQL_ERROR 74}; 75 76class [[nodiscard]] Result { 77public: 78 ALWAYS_INLINE Result(SQLCommand command) 79 : m_command(command) 80 { 81 } 82 83 ALWAYS_INLINE Result(SQLCommand command, SQLErrorCode error) 84 : m_command(command) 85 , m_error(error) 86 { 87 } 88 89 ALWAYS_INLINE Result(SQLCommand command, SQLErrorCode error, DeprecatedString error_message) 90 : m_command(command) 91 , m_error(error) 92 , m_error_message(move(error_message)) 93 { 94 } 95 96 ALWAYS_INLINE Result(Error error) 97 : m_error(SQLErrorCode::InternalError) 98 , m_error_message(error.string_literal()) 99 { 100 } 101 102 Result(Result&&) = default; 103 Result& operator=(Result&&) = default; 104 105 SQLCommand command() const { return m_command; } 106 SQLErrorCode error() const { return m_error; } 107 DeprecatedString error_string() const; 108 109 // These are for compatibility with the TRY() macro in AK. 110 [[nodiscard]] bool is_error() const { return m_error != SQLErrorCode::NoError; } 111 [[nodiscard]] Result release_value() { return move(*this); } 112 Result release_error() 113 { 114 VERIFY(is_error()); 115 116 if (m_error_message.has_value()) 117 return { m_command, m_error, m_error_message.release_value() }; 118 return { m_command, m_error }; 119 } 120 121private: 122 AK_MAKE_NONCOPYABLE(Result); 123 124 SQLCommand m_command { SQLCommand::Unknown }; 125 126 SQLErrorCode m_error { SQLErrorCode::NoError }; 127 Optional<DeprecatedString> m_error_message {}; 128}; 129 130template<typename ValueType> 131using ResultOr = ErrorOr<ValueType, Result>; 132 133}