5#if defined(_WIN32) || defined(_WIN64)
12#include <source_location>
14#include <system_error>
30 SQLINTEGER nativeErrorCode {};
31 std::string sqlState =
" ";
37 return fromHandle(SQL_HANDLE_DBC, hDbc);
43 return fromHandle(SQL_HANDLE_STMT, hStmt);
50 static SqlErrorInfo fromHandle(SQLSMALLINT handleType, SQLHANDLE handle)
53 info.message = std::string(1024,
'\0');
55 SQLSMALLINT msgLen {};
56 SQLGetDiagRecA(handleType,
59 (SQLCHAR*) info.sqlState.data(),
60 &info.nativeErrorCode,
61 (SQLCHAR*) info.message.data(),
62 (SQLSMALLINT) info.message.capacity(),
64 info.message.resize(msgLen);
69class SqlException:
public std::runtime_error
73 std::source_location location = std::source_location::current());
75 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE
SqlErrorInfo const& info() const noexcept
84enum class SqlError : std::int16_t
86 SUCCESS = SQL_SUCCESS,
87 SUCCESS_WITH_INFO = SQL_SUCCESS_WITH_INFO,
90 INVALID_HANDLE = SQL_INVALID_HANDLE,
91 STILL_EXECUTING = SQL_STILL_EXECUTING,
92 NEED_DATA = SQL_NEED_DATA,
93 PARAM_DATA_AVAILABLE = SQL_PARAM_DATA_AVAILABLE,
94 NO_DATA_FOUND = SQL_NO_DATA_FOUND,
95 UNSUPPORTED_TYPE = 1'000,
96 INVALID_ARGUMENT = 1'001,
97 TRANSACTION_ERROR = 1'002,
100struct SqlErrorCategory: std::error_category
102 static SqlErrorCategory
const& get() noexcept
104 static SqlErrorCategory
const category;
107 [[nodiscard]]
const char* name() const noexcept
override
109 return "Lightweight";
112 [[nodiscard]] std::string message(
int code)
const override
114 using namespace std::string_literals;
115 switch (
static_cast<SqlError
>(code))
117 case SqlError::SUCCESS:
118 return "SQL_SUCCESS"s;
119 case SqlError::SUCCESS_WITH_INFO:
120 return "SQL_SUCCESS_WITH_INFO"s;
121 case SqlError::NODATA:
122 return "SQL_NO_DATA"s;
123 case SqlError::FAILURE:
125 case SqlError::INVALID_HANDLE:
126 return "SQL_INVALID_HANDLE"s;
127 case SqlError::STILL_EXECUTING:
128 return "SQL_STILL_EXECUTING"s;
129 case SqlError::NEED_DATA:
130 return "SQL_NEED_DATA"s;
131 case SqlError::PARAM_DATA_AVAILABLE:
132 return "SQL_PARAM_DATA_AVAILABLE"s;
133 case SqlError::UNSUPPORTED_TYPE:
134 return "SQL_UNSUPPORTED_TYPE"s;
135 case SqlError::INVALID_ARGUMENT:
136 return "SQL_INVALID_ARGUMENT"s;
137 case SqlError::TRANSACTION_ERROR:
138 return "SQL_TRANSACTION_ERROR"s;
140 return std::format(
"SQL error code {}", code);
146struct std::is_error_code_enum<SqlError>:
public std::true_type
151inline std::error_code make_error_code(SqlError e)
153 return {
static_cast<int>(e), SqlErrorCategory::get() };
157struct LIGHTWEIGHT_API std::formatter<SqlError>: formatter<std::string>
159 auto format(SqlError value, format_context& ctx)
const -> format_context::iterator
161 return formatter<std::string>::format(std::format(
"{}", SqlErrorCategory().message(
static_cast<int>(value))),
167struct LIGHTWEIGHT_API std::formatter<SqlErrorInfo>: formatter<std::string>
169 auto format(
SqlErrorInfo const& info, format_context& ctx)
const -> format_context::iterator
171 return formatter<std::string>::format(
172 std::format(
"{} ({}) - {}", info.sqlState, info.nativeErrorCode, info.message), ctx);
Represents an ODBC SQL error.
static SqlErrorInfo fromConnectionHandle(SQLHDBC hDbc)
Constructs an ODBC error info object from the given ODBC connection handle.
static void RequireStatementSuccess(SQLRETURN result, SQLHSTMT hStmt, std::string_view message)
Asserts that the given result is a success code, otherwise throws an exception.
static SqlErrorInfo fromStatementHandle(SQLHSTMT hStmt)
Constructs an ODBC error info object from the given ODBC statement handle.