| 1 | #include "duckdb/main/error_manager.hpp" |
| 2 | #include "duckdb/main/config.hpp" |
| 3 | #include "utf8proc_wrapper.hpp" |
| 4 | |
| 5 | namespace duckdb { |
| 6 | |
| 7 | struct DefaultError { |
| 8 | ErrorType type; |
| 9 | const char *error; |
| 10 | }; |
| 11 | |
| 12 | static DefaultError internal_errors[] = { |
| 13 | {.type: ErrorType::UNSIGNED_EXTENSION, |
| 14 | .error: "Extension \"%s\" could not be loaded because its signature is either missing or invalid and unsigned extensions " |
| 15 | "are disabled by configuration (allow_unsigned_extensions)" }, |
| 16 | {.type: ErrorType::INVALIDATED_TRANSACTION, .error: "Current transaction is aborted (please ROLLBACK)" }, |
| 17 | {.type: ErrorType::INVALIDATED_DATABASE, .error: "Failed: database has been invalidated because of a previous fatal error. The " |
| 18 | "database must be restarted prior to being used again.\nOriginal error: \"%s\"" }, |
| 19 | {.type: ErrorType::INVALID, .error: nullptr}}; |
| 20 | |
| 21 | string ErrorManager::FormatExceptionRecursive(ErrorType error_type, vector<ExceptionFormatValue> &values) { |
| 22 | if (error_type >= ErrorType::ERROR_COUNT) { |
| 23 | throw InternalException("Invalid error type passed to ErrorManager::FormatError" ); |
| 24 | } |
| 25 | auto entry = custom_errors.find(x: error_type); |
| 26 | string error; |
| 27 | if (entry == custom_errors.end()) { |
| 28 | // error was not overwritten |
| 29 | error = internal_errors[int(error_type)].error; |
| 30 | } else { |
| 31 | // error was overwritten |
| 32 | error = entry->second; |
| 33 | } |
| 34 | return ExceptionFormatValue::Format(msg: error, values); |
| 35 | } |
| 36 | |
| 37 | string ErrorManager::InvalidUnicodeError(const string &input, const string &context) { |
| 38 | UnicodeInvalidReason reason; |
| 39 | size_t pos; |
| 40 | auto unicode = Utf8Proc::Analyze(s: const_char_ptr_cast(src: input.c_str()), len: input.size(), invalid_reason: &reason, invalid_pos: &pos); |
| 41 | if (unicode != UnicodeType::INVALID) { |
| 42 | return "Invalid unicode error thrown but no invalid unicode detected in " + context; |
| 43 | } |
| 44 | string base_message; |
| 45 | switch (reason) { |
| 46 | case UnicodeInvalidReason::BYTE_MISMATCH: |
| 47 | base_message = "Invalid unicode (byte sequence mismatch)" ; |
| 48 | break; |
| 49 | case UnicodeInvalidReason::INVALID_UNICODE: |
| 50 | base_message = "Invalid unicode" ; |
| 51 | break; |
| 52 | default: |
| 53 | break; |
| 54 | } |
| 55 | return base_message + " detected in " + context; |
| 56 | } |
| 57 | |
| 58 | void ErrorManager::AddCustomError(ErrorType type, string new_error) { |
| 59 | custom_errors.insert(x: make_pair(x&: type, y: std::move(new_error))); |
| 60 | } |
| 61 | |
| 62 | ErrorManager &ErrorManager::Get(ClientContext &context) { |
| 63 | return *DBConfig::GetConfig(context).error_manager; |
| 64 | } |
| 65 | |
| 66 | ErrorManager &ErrorManager::Get(DatabaseInstance &context) { |
| 67 | return *DBConfig::GetConfig(db&: context).error_manager; |
| 68 | } |
| 69 | |
| 70 | } // namespace duckdb |
| 71 | |