5#if defined(_WIN32) || defined(_WIN64)
13#include <source_location>
15#include <system_error>
34 SQLINTEGER nativeErrorCode {};
35 std::string sqlState =
" ";
41 return FromHandle(SQL_HANDLE_DBC, hDbc);
47 return FromHandle(SQL_HANDLE_STMT, hStmt);
53 return FromHandle(SQL_HANDLE_ENV, hEnv);
60 static SqlErrorInfo FromHandle(SQLSMALLINT handleType, SQLHANDLE handle)
63 info.message = std::string(1024,
'\0');
65 SQLSMALLINT msgLen {};
66 SQLGetDiagRecA(handleType,
69 (SQLCHAR*) info.sqlState.data(),
70 &info.nativeErrorCode,
71 (SQLCHAR*) info.message.data(),
72 (SQLSMALLINT) info.message.capacity(),
74 info.message.resize(
static_cast<size_t>(msgLen));
79class SqlException:
public std::runtime_error
82 LIGHTWEIGHT_API
explicit SqlException(SqlErrorInfo info,
83 std::source_location location = std::source_location::current());
86 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE SqlErrorInfo
const& info() const noexcept
95enum class SqlError : std::int16_t
97 SUCCESS = SQL_SUCCESS,
98 SUCCESS_WITH_INFO = SQL_SUCCESS_WITH_INFO,
101 INVALID_HANDLE = SQL_INVALID_HANDLE,
102 STILL_EXECUTING = SQL_STILL_EXECUTING,
103 NEED_DATA = SQL_NEED_DATA,
104 PARAM_DATA_AVAILABLE = SQL_PARAM_DATA_AVAILABLE,
105 NO_DATA_FOUND = SQL_NO_DATA_FOUND,
106 UNSUPPORTED_TYPE = 1'000,
107 INVALID_ARGUMENT = 1'001,
108 TRANSACTION_ERROR = 1'002,
111struct SqlErrorCategory: std::error_category
114 static SqlErrorCategory
const& get() noexcept
116 static SqlErrorCategory
const category;
120 [[nodiscard]]
char const* name() const noexcept
override
122 return "Lightweight";
125 [[nodiscard]] std::string message(
int code)
const override
127 using namespace std::string_literals;
128 switch (
static_cast<SqlError
>(code))
130 case SqlError::SUCCESS:
131 return "SQL_SUCCESS"s;
132 case SqlError::SUCCESS_WITH_INFO:
133 return "SQL_SUCCESS_WITH_INFO"s;
134 case SqlError::NODATA:
135 return "SQL_NO_DATA"s;
136 case SqlError::FAILURE:
138 case SqlError::INVALID_HANDLE:
139 return "SQL_INVALID_HANDLE"s;
140 case SqlError::STILL_EXECUTING:
141 return "SQL_STILL_EXECUTING"s;
142 case SqlError::NEED_DATA:
143 return "SQL_NEED_DATA"s;
144 case SqlError::PARAM_DATA_AVAILABLE:
145 return "SQL_PARAM_DATA_AVAILABLE"s;
146 case SqlError::UNSUPPORTED_TYPE:
147 return "SQL_UNSUPPORTED_TYPE"s;
148 case SqlError::INVALID_ARGUMENT:
149 return "SQL_INVALID_ARGUMENT"s;
150 case SqlError::TRANSACTION_ERROR:
151 return "SQL_TRANSACTION_ERROR"s;
153 return std::format(
"SQL error code {}", code);
161struct std::is_error_code_enum<Lightweight::SqlError>:
public std::true_type
167inline std::error_code make_error_code(Lightweight::SqlError e)
169 return {
static_cast<int>(e), Lightweight::SqlErrorCategory::get() };
173struct std::formatter<Lightweight::SqlError>: formatter<std::string>
175 auto format(Lightweight::SqlError value, format_context& ctx)
const -> format_context::iterator
177 return formatter<std::string>::format(
178 std::format(
"{}", Lightweight::SqlErrorCategory().message(
static_cast<int>(value))), ctx);
183struct std::formatter<Lightweight::SqlErrorInfo>: formatter<std::string>
187 return formatter<std::string>::format(std::format(
"{} ({}) - {}", info.sqlState, info.nativeErrorCode, info.message),
Represents an ODBC SQL error.
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.
static SqlErrorInfo FromEnvironmentHandle(SQLHENV hEnv)
Constructs an ODBC error info object from the given ODBC environment handle.
static SqlErrorInfo FromConnectionHandle(SQLHDBC hDbc)
Constructs an ODBC error info object from the given ODBC connection handle.