5#if defined(_WIN32) || defined(_WIN64)
13#include <source_location>
15#include <system_error>
44 return FromHandle(SQL_HANDLE_DBC, hDbc);
50 return FromHandle(SQL_HANDLE_STMT, hStmt);
56 return FromHandle(SQL_HANDLE_ENV, hEnv);
63 static SqlErrorInfo FromHandle(SQLSMALLINT handleType, SQLHANDLE handle)
66 info.
message = std::string(1024,
'\0');
68 SQLSMALLINT msgLen {};
69 SQLGetDiagRecA(handleType,
72 (SQLCHAR*) info.sqlState.data(),
73 &info.nativeErrorCode,
74 (SQLCHAR*) info.message.data(),
75 (SQLSMALLINT) info.message.capacity(),
77 info.message.resize(
static_cast<size_t>(msgLen));
82class SqlException:
public std::runtime_error
85 LIGHTWEIGHT_API
explicit SqlException(SqlErrorInfo info,
86 std::source_location location = std::source_location::current());
89 [[nodiscard]] LIGHTWEIGHT_FORCE_INLINE SqlErrorInfo
const& info() const noexcept
98enum class SqlError : std::int16_t
100 SUCCESS = SQL_SUCCESS,
101 SUCCESS_WITH_INFO = SQL_SUCCESS_WITH_INFO,
102 NODATA = SQL_NO_DATA,
104 INVALID_HANDLE = SQL_INVALID_HANDLE,
105 STILL_EXECUTING = SQL_STILL_EXECUTING,
106 NEED_DATA = SQL_NEED_DATA,
107 PARAM_DATA_AVAILABLE = SQL_PARAM_DATA_AVAILABLE,
108 NO_DATA_FOUND = SQL_NO_DATA_FOUND,
109 UNSUPPORTED_TYPE = 1'000,
110 INVALID_ARGUMENT = 1'001,
111 TRANSACTION_ERROR = 1'002,
114struct SqlErrorCategory: std::error_category
117 static SqlErrorCategory
const& get() noexcept
119 static SqlErrorCategory
const category;
123 [[nodiscard]]
char const* name() const noexcept
override
125 return "Lightweight";
128 [[nodiscard]] std::string message(
int code)
const override
130 using namespace std::string_literals;
131 switch (
static_cast<SqlError
>(code))
133 case SqlError::SUCCESS:
134 return "SQL_SUCCESS"s;
135 case SqlError::SUCCESS_WITH_INFO:
136 return "SQL_SUCCESS_WITH_INFO"s;
137 case SqlError::NODATA:
138 return "SQL_NO_DATA"s;
139 case SqlError::FAILURE:
141 case SqlError::INVALID_HANDLE:
142 return "SQL_INVALID_HANDLE"s;
143 case SqlError::STILL_EXECUTING:
144 return "SQL_STILL_EXECUTING"s;
145 case SqlError::NEED_DATA:
146 return "SQL_NEED_DATA"s;
147 case SqlError::PARAM_DATA_AVAILABLE:
148 return "SQL_PARAM_DATA_AVAILABLE"s;
149 case SqlError::UNSUPPORTED_TYPE:
150 return "SQL_UNSUPPORTED_TYPE"s;
151 case SqlError::INVALID_ARGUMENT:
152 return "SQL_INVALID_ARGUMENT"s;
153 case SqlError::TRANSACTION_ERROR:
154 return "SQL_TRANSACTION_ERROR"s;
156 return std::format(
"SQL error code {}", code);
164struct std::is_error_code_enum<Lightweight::SqlError>:
public std::true_type
170inline std::error_code make_error_code(Lightweight::SqlError e)
172 return {
static_cast<int>(e), Lightweight::SqlErrorCategory::get() };
176struct std::formatter<Lightweight::SqlError>: formatter<std::string>
178 auto format(Lightweight::SqlError value, format_context& ctx)
const -> format_context::iterator
180 return formatter<std::string>::format(
181 std::format(
"{}", Lightweight::SqlErrorCategory().message(
static_cast<int>(value))), ctx);
186struct std::formatter<Lightweight::SqlErrorInfo>: formatter<std::string>
190 return formatter<std::string>::format(std::format(
"{} ({}) - {}", info.sqlState, info.nativeErrorCode, info.message),
Represents an ODBC SQL error.
SQLINTEGER nativeErrorCode
The native ODBC error code.
std::string message
The human-readable error message.
static void RequireStatementSuccess(SQLRETURN result, SQLHSTMT hStmt, std::string_view message)
Asserts that the given result is a success code, otherwise throws an exception.
std::string sqlState
The SQLSTATE diagnostic code (5 characters).
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.