Serenity Operating System
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}