mirror of
				https://github.com/RGBCube/serenity
				synced 2025-10-31 11:32:43 +00:00 
			
		
		
		
	 66f98237a7
			
		
	
	
		66f98237a7
		
	
	
	
	
		
			
			This makes error invocations such as Error::from_string_literal become
associated with a SQLErrorCode (typically 0, AmbiguousColumnName). The
result, when displayed to the user, is quite confusing, e.g.:
    Column name 'Heap()::write_block(): Oversized block' is ambiguous
Instead, just interpret these as internal errors, so the error message
is displayed as-is.
		
	
			
		
			
				
	
	
		
			133 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			133 lines
		
	
	
	
		
			5 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| /*
 | |
|  * Copyright (c) 2021, Jan de Visser <jan@de-visser.net>
 | |
|  * Copyright (c) 2021, Mahmoud Mandour <ma.mandourr@gmail.com>
 | |
|  *
 | |
|  * SPDX-License-Identifier: BSD-2-Clause
 | |
|  */
 | |
| 
 | |
| #pragma once
 | |
| 
 | |
| #include <AK/Error.h>
 | |
| #include <AK/Noncopyable.h>
 | |
| #include <LibSQL/Type.h>
 | |
| 
 | |
| namespace SQL {
 | |
| 
 | |
| #define ENUMERATE_SQL_COMMANDS(S) \
 | |
|     S(Unknown)                    \
 | |
|     S(Create)                     \
 | |
|     S(Delete)                     \
 | |
|     S(Describe)                   \
 | |
|     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(AmbiguousColumnName, "Column name '{}' is ambiguous")                                       \
 | |
|     S(BooleanOperatorTypeMismatch, "Cannot apply '{}' operator to non-boolean operands")          \
 | |
|     S(ColumnDoesNotExist, "Column '{}' does not exist")                                           \
 | |
|     S(DatabaseDoesNotExist, "Database '{}' does not exist")                                       \
 | |
|     S(DatabaseUnavailable, "Database Unavailable")                                                \
 | |
|     S(IntegerOperatorTypeMismatch, "Cannot apply '{}' operator to non-numeric operands")          \
 | |
|     S(IntegerOverflow, "Operation would cause integer overflow")                                  \
 | |
|     S(InternalError, "{}")                                                                        \
 | |
|     S(InvalidDatabaseName, "Invalid database name '{}'")                                          \
 | |
|     S(InvalidNumberOfPlaceholderValues, "Number of values does not match number of placeholders") \
 | |
|     S(InvalidNumberOfValues, "Number of values does not match number of columns")                 \
 | |
|     S(InvalidOperator, "Invalid operator '{}'")                                                   \
 | |
|     S(InvalidType, "Invalid type '{}'")                                                           \
 | |
|     S(InvalidValueType, "Invalid type for attribute '{}'")                                        \
 | |
|     S(NoError, "No error")                                                                        \
 | |
|     S(NotYetImplemented, "{}")                                                                    \
 | |
|     S(NumericOperatorTypeMismatch, "Cannot apply '{}' operator to non-numeric operands")          \
 | |
|     S(SchemaDoesNotExist, "Schema '{}' does not exist")                                           \
 | |
|     S(SchemaExists, "Schema '{}' already exist")                                                  \
 | |
|     S(StatementUnavailable, "Statement with id '{}' Unavailable")                                 \
 | |
|     S(SyntaxError, "Syntax Error")                                                                \
 | |
|     S(TableDoesNotExist, "Table '{}' does not exist")                                             \
 | |
|     S(TableExists, "Table '{}' already exist")
 | |
| 
 | |
| enum class SQLErrorCode {
 | |
| #undef __ENUMERATE_SQL_ERROR
 | |
| #define __ENUMERATE_SQL_ERROR(error, description) error,
 | |
|     ENUMERATE_SQL_ERRORS(__ENUMERATE_SQL_ERROR)
 | |
| #undef __ENUMERATE_SQL_ERROR
 | |
| };
 | |
| 
 | |
| class [[nodiscard]] Result {
 | |
| public:
 | |
|     ALWAYS_INLINE Result(SQLCommand command)
 | |
|         : m_command(command)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     ALWAYS_INLINE Result(SQLCommand command, SQLErrorCode error)
 | |
|         : m_command(command)
 | |
|         , m_error(error)
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     ALWAYS_INLINE Result(SQLCommand command, SQLErrorCode error, DeprecatedString error_message)
 | |
|         : m_command(command)
 | |
|         , m_error(error)
 | |
|         , m_error_message(move(error_message))
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     ALWAYS_INLINE Result(Error error)
 | |
|         : m_error(SQLErrorCode::InternalError)
 | |
|         , m_error_message(error.string_literal())
 | |
|     {
 | |
|     }
 | |
| 
 | |
|     Result(Result&&) = default;
 | |
|     Result& operator=(Result&&) = default;
 | |
| 
 | |
|     SQLCommand command() const { return m_command; }
 | |
|     SQLErrorCode error() const { return m_error; }
 | |
|     DeprecatedString error_string() const;
 | |
| 
 | |
|     // These are for compatibility with the TRY() macro in AK.
 | |
|     [[nodiscard]] bool is_error() const { return m_error != SQLErrorCode::NoError; }
 | |
|     [[nodiscard]] Result release_value() { return move(*this); }
 | |
|     Result release_error()
 | |
|     {
 | |
|         VERIFY(is_error());
 | |
| 
 | |
|         if (m_error_message.has_value())
 | |
|             return { m_command, m_error, m_error_message.release_value() };
 | |
|         return { m_command, m_error };
 | |
|     }
 | |
| 
 | |
| private:
 | |
|     AK_MAKE_NONCOPYABLE(Result);
 | |
| 
 | |
|     SQLCommand m_command { SQLCommand::Unknown };
 | |
| 
 | |
|     SQLErrorCode m_error { SQLErrorCode::NoError };
 | |
|     Optional<DeprecatedString> m_error_message {};
 | |
| };
 | |
| 
 | |
| template<typename ValueType>
 | |
| using ResultOr = ErrorOr<ValueType, Result>;
 | |
| 
 | |
| }
 |