1#include "duckdb/common/exception.hpp"
2
3#include "duckdb/common/string_util.hpp"
4#include "duckdb/common/to_string.hpp"
5#include "duckdb/common/types.hpp"
6
7#ifdef DUCKDB_CRASH_ON_ASSERT
8#include "duckdb/common/printer.hpp"
9#include <stdio.h>
10#include <stdlib.h>
11#endif
12#ifdef DUCKDB_DEBUG_STACKTRACE
13#include <execinfo.h>
14#endif
15
16namespace duckdb {
17
18Exception::Exception(const string &msg) : std::exception(), type(ExceptionType::INVALID), raw_message_(msg) {
19 exception_message_ = msg;
20}
21
22Exception::Exception(ExceptionType exception_type, const string &message)
23 : std::exception(), type(exception_type), raw_message_(message) {
24 exception_message_ = ExceptionTypeToString(type: exception_type) + " Error: " + message;
25}
26
27const char *Exception::what() const noexcept {
28 return exception_message_.c_str();
29}
30
31const string &Exception::RawMessage() const {
32 return raw_message_;
33}
34
35bool Exception::UncaughtException() {
36#if __cplusplus >= 201703L
37 return std::uncaught_exceptions() > 0;
38#else
39 return std::uncaught_exception();
40#endif
41}
42
43string Exception::GetStackTrace(int max_depth) {
44#ifdef DUCKDB_DEBUG_STACKTRACE
45 string result;
46 auto callstack = unique_ptr<void *[]>(new void *[max_depth]);
47 int frames = backtrace(callstack.get(), max_depth);
48 char **strs = backtrace_symbols(callstack.get(), frames);
49 for (int i = 0; i < frames; i++) {
50 result += strs[i];
51 result += "\n";
52 }
53 free(strs);
54 return "\n" + result;
55#else
56 // Stack trace not available. Toggle DUCKDB_DEBUG_STACKTRACE in exception.cpp to enable stack traces.
57 return "";
58#endif
59}
60
61string Exception::ConstructMessageRecursive(const string &msg, std::vector<ExceptionFormatValue> &values) {
62#ifdef DEBUG
63 // Verify that we have the required amount of values for the message
64 idx_t parameter_count = 0;
65 for (idx_t i = 0; i < msg.size(); i++) {
66 if (msg[i] != '%') {
67 continue;
68 }
69 if (i < msg.size() && msg[i + 1] == '%') {
70 i++;
71 continue;
72 }
73 parameter_count++;
74 }
75 if (parameter_count != values.size()) {
76 throw InternalException("Primary exception: %s\nSecondary exception in ConstructMessageRecursive: Expected %d "
77 "parameters, received %d",
78 msg.c_str(), parameter_count, values.size());
79 }
80
81#endif
82 return ExceptionFormatValue::Format(msg, values);
83}
84
85string Exception::ExceptionTypeToString(ExceptionType type) {
86 switch (type) {
87 case ExceptionType::INVALID:
88 return "Invalid";
89 case ExceptionType::OUT_OF_RANGE:
90 return "Out of Range";
91 case ExceptionType::CONVERSION:
92 return "Conversion";
93 case ExceptionType::UNKNOWN_TYPE:
94 return "Unknown Type";
95 case ExceptionType::DECIMAL:
96 return "Decimal";
97 case ExceptionType::MISMATCH_TYPE:
98 return "Mismatch Type";
99 case ExceptionType::DIVIDE_BY_ZERO:
100 return "Divide by Zero";
101 case ExceptionType::OBJECT_SIZE:
102 return "Object Size";
103 case ExceptionType::INVALID_TYPE:
104 return "Invalid type";
105 case ExceptionType::SERIALIZATION:
106 return "Serialization";
107 case ExceptionType::TRANSACTION:
108 return "TransactionContext";
109 case ExceptionType::NOT_IMPLEMENTED:
110 return "Not implemented";
111 case ExceptionType::EXPRESSION:
112 return "Expression";
113 case ExceptionType::CATALOG:
114 return "Catalog";
115 case ExceptionType::PARSER:
116 return "Parser";
117 case ExceptionType::BINDER:
118 return "Binder";
119 case ExceptionType::PLANNER:
120 return "Planner";
121 case ExceptionType::SCHEDULER:
122 return "Scheduler";
123 case ExceptionType::EXECUTOR:
124 return "Executor";
125 case ExceptionType::CONSTRAINT:
126 return "Constraint";
127 case ExceptionType::INDEX:
128 return "Index";
129 case ExceptionType::STAT:
130 return "Stat";
131 case ExceptionType::CONNECTION:
132 return "Connection";
133 case ExceptionType::SYNTAX:
134 return "Syntax";
135 case ExceptionType::SETTINGS:
136 return "Settings";
137 case ExceptionType::OPTIMIZER:
138 return "Optimizer";
139 case ExceptionType::NULL_POINTER:
140 return "NullPointer";
141 case ExceptionType::IO:
142 return "IO";
143 case ExceptionType::INTERRUPT:
144 return "INTERRUPT";
145 case ExceptionType::FATAL:
146 return "FATAL";
147 case ExceptionType::INTERNAL:
148 return "INTERNAL";
149 case ExceptionType::INVALID_INPUT:
150 return "Invalid Input";
151 case ExceptionType::OUT_OF_MEMORY:
152 return "Out of Memory";
153 case ExceptionType::PERMISSION:
154 return "Permission";
155 case ExceptionType::PARAMETER_NOT_RESOLVED:
156 return "Parameter Not Resolved";
157 case ExceptionType::PARAMETER_NOT_ALLOWED:
158 return "Parameter Not Allowed";
159 case ExceptionType::DEPENDENCY:
160 return "Dependency";
161 case ExceptionType::HTTP:
162 return "HTTP";
163 default:
164 return "Unknown";
165 }
166}
167
168const HTTPException &Exception::AsHTTPException() const {
169 D_ASSERT(type == ExceptionType::HTTP);
170 const auto &e = static_cast<const HTTPException *>(this);
171 D_ASSERT(e->GetStatusCode() != 0);
172 D_ASSERT(e->GetHeaders().size() > 0);
173 return *e;
174}
175
176void Exception::ThrowAsTypeWithMessage(ExceptionType type, const string &message,
177 const std::shared_ptr<Exception> &original) {
178 switch (type) {
179 case ExceptionType::OUT_OF_RANGE:
180 throw OutOfRangeException(message);
181 case ExceptionType::CONVERSION:
182 throw ConversionException(message); // FIXME: make a separation between Conversion/Cast exception?
183 case ExceptionType::INVALID_TYPE:
184 throw InvalidTypeException(message);
185 case ExceptionType::MISMATCH_TYPE:
186 throw TypeMismatchException(message);
187 case ExceptionType::TRANSACTION:
188 throw TransactionException(message);
189 case ExceptionType::NOT_IMPLEMENTED:
190 throw NotImplementedException(message);
191 case ExceptionType::CATALOG:
192 throw CatalogException(message);
193 case ExceptionType::CONNECTION:
194 throw ConnectionException(message);
195 case ExceptionType::PARSER:
196 throw ParserException(message);
197 case ExceptionType::PERMISSION:
198 throw PermissionException(message);
199 case ExceptionType::SYNTAX:
200 throw SyntaxException(message);
201 case ExceptionType::CONSTRAINT:
202 throw ConstraintException(message);
203 case ExceptionType::BINDER:
204 throw BinderException(message);
205 case ExceptionType::IO:
206 throw IOException(message);
207 case ExceptionType::SERIALIZATION:
208 throw SerializationException(message);
209 case ExceptionType::INTERRUPT:
210 throw InterruptException();
211 case ExceptionType::INTERNAL:
212 throw InternalException(message);
213 case ExceptionType::INVALID_INPUT:
214 throw InvalidInputException(message);
215 case ExceptionType::OUT_OF_MEMORY:
216 throw OutOfMemoryException(message);
217 case ExceptionType::PARAMETER_NOT_ALLOWED:
218 throw ParameterNotAllowedException(message);
219 case ExceptionType::PARAMETER_NOT_RESOLVED:
220 throw ParameterNotResolvedException();
221 case ExceptionType::FATAL:
222 throw FatalException(message);
223 case ExceptionType::DEPENDENCY:
224 throw DependencyException(message);
225 case ExceptionType::HTTP: {
226 original->AsHTTPException().Throw();
227 }
228 default:
229 throw Exception(type, message);
230 }
231}
232
233StandardException::StandardException(ExceptionType exception_type, const string &message)
234 : Exception(exception_type, message) {
235}
236
237CastException::CastException(const PhysicalType orig_type, const PhysicalType new_type)
238 : Exception(ExceptionType::CONVERSION,
239 "Type " + TypeIdToString(type: orig_type) + " can't be cast as " + TypeIdToString(type: new_type)) {
240}
241
242CastException::CastException(const LogicalType &orig_type, const LogicalType &new_type)
243 : Exception(ExceptionType::CONVERSION,
244 "Type " + orig_type.ToString() + " can't be cast as " + new_type.ToString()) {
245}
246
247CastException::CastException(const string &msg) : Exception(ExceptionType::CONVERSION, msg) {
248}
249
250ValueOutOfRangeException::ValueOutOfRangeException(const int64_t value, const PhysicalType orig_type,
251 const PhysicalType new_type)
252 : Exception(ExceptionType::CONVERSION, "Type " + TypeIdToString(type: orig_type) + " with value " +
253 to_string(val: (intmax_t)value) +
254 " can't be cast because the value is out of range "
255 "for the destination type " +
256 TypeIdToString(type: new_type)) {
257}
258
259ValueOutOfRangeException::ValueOutOfRangeException(const double value, const PhysicalType orig_type,
260 const PhysicalType new_type)
261 : Exception(ExceptionType::CONVERSION, "Type " + TypeIdToString(type: orig_type) + " with value " + to_string(val: value) +
262 " can't be cast because the value is out of range "
263 "for the destination type " +
264 TypeIdToString(type: new_type)) {
265}
266
267ValueOutOfRangeException::ValueOutOfRangeException(const hugeint_t value, const PhysicalType orig_type,
268 const PhysicalType new_type)
269 : Exception(ExceptionType::CONVERSION, "Type " + TypeIdToString(type: orig_type) + " with value " + value.ToString() +
270 " can't be cast because the value is out of range "
271 "for the destination type " +
272 TypeIdToString(type: new_type)) {
273}
274
275ValueOutOfRangeException::ValueOutOfRangeException(const PhysicalType var_type, const idx_t length)
276 : Exception(ExceptionType::OUT_OF_RANGE,
277 "The value is too long to fit into type " + TypeIdToString(type: var_type) + "(" + to_string(val: length) + ")") {
278}
279
280ValueOutOfRangeException::ValueOutOfRangeException(const string &msg) : Exception(ExceptionType::OUT_OF_RANGE, msg) {
281}
282
283ConversionException::ConversionException(const string &msg) : Exception(ExceptionType::CONVERSION, msg) {
284}
285
286InvalidTypeException::InvalidTypeException(PhysicalType type, const string &msg)
287 : Exception(ExceptionType::INVALID_TYPE, "Invalid Type [" + TypeIdToString(type) + "]: " + msg) {
288}
289
290InvalidTypeException::InvalidTypeException(const LogicalType &type, const string &msg)
291 : Exception(ExceptionType::INVALID_TYPE, "Invalid Type [" + type.ToString() + "]: " + msg) {
292}
293
294InvalidTypeException::InvalidTypeException(const string &msg) : Exception(ExceptionType::INVALID_TYPE, msg) {
295}
296
297TypeMismatchException::TypeMismatchException(const PhysicalType type_1, const PhysicalType type_2, const string &msg)
298 : Exception(ExceptionType::MISMATCH_TYPE,
299 "Type " + TypeIdToString(type: type_1) + " does not match with " + TypeIdToString(type: type_2) + ". " + msg) {
300}
301
302TypeMismatchException::TypeMismatchException(const LogicalType &type_1, const LogicalType &type_2, const string &msg)
303 : Exception(ExceptionType::MISMATCH_TYPE,
304 "Type " + type_1.ToString() + " does not match with " + type_2.ToString() + ". " + msg) {
305}
306
307TypeMismatchException::TypeMismatchException(const string &msg) : Exception(ExceptionType::MISMATCH_TYPE, msg) {
308}
309
310TransactionException::TransactionException(const string &msg) : Exception(ExceptionType::TRANSACTION, msg) {
311}
312
313NotImplementedException::NotImplementedException(const string &msg) : Exception(ExceptionType::NOT_IMPLEMENTED, msg) {
314}
315
316OutOfRangeException::OutOfRangeException(const string &msg) : Exception(ExceptionType::OUT_OF_RANGE, msg) {
317}
318
319CatalogException::CatalogException(const string &msg) : StandardException(ExceptionType::CATALOG, msg) {
320}
321
322ConnectionException::ConnectionException(const string &msg) : StandardException(ExceptionType::CONNECTION, msg) {
323}
324
325ParserException::ParserException(const string &msg) : StandardException(ExceptionType::PARSER, msg) {
326}
327
328PermissionException::PermissionException(const string &msg) : StandardException(ExceptionType::PERMISSION, msg) {
329}
330
331SyntaxException::SyntaxException(const string &msg) : Exception(ExceptionType::SYNTAX, msg) {
332}
333
334ConstraintException::ConstraintException(const string &msg) : Exception(ExceptionType::CONSTRAINT, msg) {
335}
336
337DependencyException::DependencyException(const string &msg) : Exception(ExceptionType::DEPENDENCY, msg) {
338}
339
340BinderException::BinderException(const string &msg) : StandardException(ExceptionType::BINDER, msg) {
341}
342
343IOException::IOException(const string &msg) : Exception(ExceptionType::IO, msg) {
344}
345
346MissingExtensionException::MissingExtensionException(const string &msg)
347 : Exception(ExceptionType::MISSING_EXTENSION, msg) {
348}
349
350SerializationException::SerializationException(const string &msg) : Exception(ExceptionType::SERIALIZATION, msg) {
351}
352
353SequenceException::SequenceException(const string &msg) : Exception(ExceptionType::SERIALIZATION, msg) {
354}
355
356InterruptException::InterruptException() : Exception(ExceptionType::INTERRUPT, "Interrupted!") {
357}
358
359FatalException::FatalException(ExceptionType type, const string &msg) : Exception(type, msg) {
360}
361
362InternalException::InternalException(const string &msg) : FatalException(ExceptionType::INTERNAL, msg) {
363#ifdef DUCKDB_CRASH_ON_ASSERT
364 Printer::Print("ABORT THROWN BY INTERNAL EXCEPTION: " + msg);
365 abort();
366#endif
367}
368
369InvalidInputException::InvalidInputException(const string &msg) : Exception(ExceptionType::INVALID_INPUT, msg) {
370}
371
372OutOfMemoryException::OutOfMemoryException(const string &msg) : Exception(ExceptionType::OUT_OF_MEMORY, msg) {
373}
374
375ParameterNotAllowedException::ParameterNotAllowedException(const string &msg)
376 : StandardException(ExceptionType::PARAMETER_NOT_ALLOWED, msg) {
377}
378
379ParameterNotResolvedException::ParameterNotResolvedException()
380 : Exception(ExceptionType::PARAMETER_NOT_RESOLVED, "Parameter types could not be resolved") {
381}
382
383} // namespace duckdb
384