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