30#include <fmt/format.h>
36namespace adbc::driver {
49 :
Status(code, std::move(message), {}) {}
53 :
Status(code, std::string(message), {}) {}
57 std::vector<std::pair<std::string, std::string>> details)
58 : impl_(std::make_unique<
Impl>(code, std::move(message), std::move(details))) {
63 bool ok()
const {
return impl_ ==
nullptr; }
66 void AddDetail(std::string key, std::string value) {
67 assert(impl_ !=
nullptr);
68 impl_->details.push_back({std::move(key), std::move(value)});
73 assert(impl_ !=
nullptr);
74 std::memset(impl_->sql_state, 0,
sizeof(impl_->sql_state));
75 for (
size_t i = 0; i < sqlstate.size(); i++) {
76 if (i >=
sizeof(impl_->sql_state)) {
80 impl_->sql_state[i] = sqlstate[i];
87 if (adbc_error ==
nullptr)
return impl_->code;
90 adbc_error->
release(adbc_error);
94 auto error_owned_by_adbc_error =
95 new Status(impl_->code, std::move(impl_->message), std::move(impl_->details));
97 const_cast<char*
>(error_owned_by_adbc_error->impl_->message.c_str());
100 adbc_error->
message =
new char[impl_->message.size() + 1];
101 if (adbc_error->
message !=
nullptr) {
102 std::memcpy(adbc_error->
message, impl_->message.c_str(),
103 impl_->message.size() + 1);
107 std::memcpy(adbc_error->
sqlstate, impl_->sql_state,
sizeof(impl_->sql_state));
108 adbc_error->
release = &CRelease;
130#define STATUS_CTOR(NAME, CODE) \
131 template <typename... Args> \
132 [[maybe_unused]] static Status NAME(Args&&... args) { \
133 std::stringstream ss; \
134 ([&] { ss << args; }(), ...); \
135 return Status(ADBC_STATUS_##CODE, ss.str()); \
138 STATUS_CTOR(Internal, INTERNAL)
139 STATUS_CTOR(InvalidArgument, INVALID_ARGUMENT)
140 STATUS_CTOR(InvalidState, INVALID_STATE)
142 STATUS_CTOR(NotFound, NOT_FOUND)
143 STATUS_CTOR(NotImplemented, NOT_IMPLEMENTED)
144 STATUS_CTOR(Unknown, UNKNOWN)
154 std::vector<std::pair<std::string, std::string>> details;
158 std::vector<std::pair<std::string, std::string>> details)
159 : code(code), message(std::move(message)), details(std::move(details)) {
160 std::memset(sql_state, 0,
sizeof(sql_state));
164 std::unique_ptr<Impl> impl_;
167 template <
typename DatabaseT,
typename ConnectionT,
typename StatementT>
172 int CDetailCount()
const {
return impl_ ?
static_cast<int>(impl_->details.size()) : 0; }
175 if (!impl_ || index < 0 ||
static_cast<size_t>(index) >= impl_->details.size()) {
176 return {
nullptr,
nullptr, 0};
178 const auto& detail = impl_->details[index];
179 return {detail.first.c_str(),
reinterpret_cast<const uint8_t*
>(detail.second.data()),
180 detail.second.size()};
184 static void CRelease(AdbcError* error) {
206 : value_(std::move(s)) {
207 assert(!std::get<Status>(value_).ok());
210 template <
typename U,
214 typename E =
typename std::enable_if<
215 std::is_constructible<T, U>::value && std::is_convertible<U, T>::value &&
216 !std::is_same<
typename std::remove_reference<
217 typename std::remove_cv<U>::type>::type,
219 Result(U&& t) : value_(std::forward<U>(t)) {}
222 bool has_value()
const {
return !std::holds_alternative<Status>(value_); }
226 assert(std::holds_alternative<Status>(value_));
227 return std::get<Status>(value_);
232 assert(std::holds_alternative<Status>(value_));
233 return std::move(std::get<Status>(value_));
238 assert(!std::holds_alternative<Status>(value_));
239 return std::get<T>(value_);
243 std::variant<Status, T> value_;
246#define RESULT_NAME_SUFFIX _adbc_framework_result
247#define RAISE_RESULT_IMPL(NAME, ERROR, LHS, RHS) \
249 auto&& NAME = (RHS); \
250 if (!(NAME).has_value()) { \
251 return (NAME).status().ToAdbc(ERROR); \
253 LHS = std::move((NAME).value()); \
256#define RAISE_STATUS_IMPL(NAME, ERROR, RHS) \
258 auto&& NAME = (RHS); \
259 if (!(NAME).ok()) { \
260 return (NAME).ToAdbc(ERROR); \
264#define UNWRAP_RESULT_IMPL(name, lhs, rhs) \
266 auto&& name = (rhs); \
267 if (!(name).has_value()) { \
268 return std::move(name).status(); \
270 lhs = std::move((name).value()); \
273#define UNWRAP_STATUS_IMPL(name, rhs) \
275 auto&& name = (rhs); \
276 if (!(name).ok()) { \
277 return std::move(name); \
281#define DRIVER_CONCAT(x, y) x##y
282#define UNWRAP_RESULT_NAME(x, y) DRIVER_CONCAT(x, y)
285#define RAISE_RESULT(ERROR, LHS, RHS) \
286 RAISE_RESULT_IMPL(UNWRAP_RESULT_NAME(driver_raise_result, RESULT_NAME_SUFFIX), ERROR, \
289#define RAISE_STATUS(ERROR, RHS) \
290 RAISE_STATUS_IMPL(UNWRAP_RESULT_NAME(driver_raise_status, RESULT_NAME_SUFFIX), ERROR, \
293#define UNWRAP_RESULT(lhs, rhs) \
294 UNWRAP_RESULT_IMPL(UNWRAP_RESULT_NAME(driver_unwrap_result, RESULT_NAME_SUFFIX), lhs, \
297#define UNWRAP_STATUS(rhs) \
298 UNWRAP_STATUS_IMPL(UNWRAP_RESULT_NAME(driver_unwrap_status, RESULT_NAME_SUFFIX), rhs)
302namespace adbc::driver::status {
304inline driver::Status Ok() {
return driver::Status(); }
306#define STATUS_CTOR(NAME, CODE) \
307 template <typename... Args> \
308 [[maybe_unused]] static Status NAME(Args&&... args) { \
309 std::stringstream ss; \
310 ([&] { ss << args; }(), ...); \
311 return Status(ADBC_STATUS_##CODE, ss.str()); \
315STATUS_CTOR(Internal, INTERNAL)
316STATUS_CTOR(InvalidArgument, INVALID_ARGUMENT)
317STATUS_CTOR(InvalidState, INVALID_STATE)
319STATUS_CTOR(NotFound, NOT_FOUND)
320STATUS_CTOR(NotImplemented, NOT_IMPLEMENTED)
321STATUS_CTOR(Unknown, UNKNOWN)
327namespace adbc::driver::status::fmt {
329#define STATUS_CTOR(NAME, CODE) \
330 template <typename... Args> \
331 [[maybe_unused]] static Status NAME(std::string_view format_string, Args&&... args) { \
332 auto message = ::fmt::vformat(format_string, ::fmt::make_format_args(args...)); \
333 return Status(ADBC_STATUS_##CODE, std::move(message)); \
337STATUS_CTOR(Internal, INTERNAL)
338STATUS_CTOR(InvalidArgument, INVALID_ARGUMENT)
339STATUS_CTOR(InvalidState, INVALID_STATE)
341STATUS_CTOR(NotFound, NOT_FOUND)
342STATUS_CTOR(NotImplemented, NOT_IMPLEMENTED)
343STATUS_CTOR(Unknown, UNKNOWN)
349#define UNWRAP_ERRNO_IMPL(NAME, CODE, RHS) \
351 auto&& NAME = (RHS); \
353 return adbc::driver::status::CODE("Call failed: ", #RHS, " = (errno ", NAME, ") ", \
354 std::strerror(NAME)); \
358#define UNWRAP_ERRNO(CODE, RHS) \
359 UNWRAP_ERRNO_IMPL(UNWRAP_RESULT_NAME(driver_errno, RESULT_NAME_SUFFIX), CODE, RHS)
361#define UNWRAP_NANOARROW_IMPL(NAME, ERROR, CODE, RHS) \
363 auto&& NAME = (RHS); \
365 return adbc::driver::status::CODE("nanoarrow call failed: ", #RHS, " = (", NAME, \
366 ") ", std::strerror(NAME), ". ", \
371#define UNWRAP_NANOARROW(ERROR, CODE, RHS) \
372 UNWRAP_NANOARROW_IMPL(UNWRAP_RESULT_NAME(driver_errno_na, RESULT_NAME_SUFFIX), ERROR, \
Status && status() &&
Move the status (if present).
Definition status.h:231
Result(U &&t)
Implicit constructor to allow returning a value in functions.
Definition status.h:219
bool has_value() const
Check if this has a value or not.
Definition status.h:222
Result(Status s)
Implicit constructor to allow returning a status in functions.
Definition status.h:205
T & value()
Get the value (if present).
Definition status.h:237
const Status & status() const &
Get the status (if present).
Definition status.h:225
A wrapper around AdbcStatusCode + AdbcError.
Definition status.h:42
Status(AdbcStatusCode code, std::string message, std::vector< std::pair< std::string, std::string > > details)
Construct a non-OK status with a message and details.
Definition status.h:56
Status()
Construct an OK status.
Definition status.h:45
AdbcStatusCode ToAdbc(AdbcError *adbc_error) const
Export this status to an AdbcError.
Definition status.h:85
bool ok() const
Check if this is an error or not.
Definition status.h:63
Status(AdbcStatusCode code, std::string message)
Construct a non-OK status with a message.
Definition status.h:48
void AddDetail(std::string key, std::string value)
Add another error detail.
Definition status.h:66
Status(AdbcStatusCode code, const char *message)
Construct a non-OK status with a message.
Definition status.h:52
void SetSqlState(std::string sqlstate)
Set the sqlstate of this status.
Definition status.h:72
int32_t vendor_code
A vendor-specific error code, if applicable.
Definition adbc.h:288
void * private_data
Opaque implementation-defined state.
Definition adbc.h:308
char * message
The error message.
Definition adbc.h:285
char sqlstate[5]
A SQLSTATE error code, if provided, as defined by the SQL:2003 standard. If not set,...
Definition adbc.h:293
void(*) release(struct AdbcError *error)
Release the contained error.
Definition adbc.h:299
#define ADBC_ERROR_VENDOR_CODE_PRIVATE_DATA
Inform the driver/driver manager that we are using the extended AdbcError struct from ADBC 1....
Definition adbc.h:271
uint8_t AdbcStatusCode
Error codes for operations that may fail.
Definition adbc.h:176
#define ADBC_ERROR_1_1_0_SIZE
The size of the AdbcError structure in ADBC 1.1.0.
Definition adbc.h:356
#define ADBC_STATUS_OK
No error.
Definition adbc.h:179
#define ADBC_ERROR_1_0_0_SIZE
The size of the AdbcError structure in ADBC 1.0.0.
Definition adbc.h:347
A detailed error message for an operation.
Definition adbc.h:283
Extra key-value metadata for an error.
Definition adbc.h:365
Private Status implementation details.
Definition status.h:150