fb-cpp 0.0.2
A modern C++ wrapper for the Firebird database API
Loading...
Searching...
No Matches
Exception.h
1/*
2 * MIT License
3 *
4 * Copyright (c) 2025 Adriano dos Santos Fernandes
5 *
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
12 *
13 * The above copyright notice and this permission notice shall be included in all
14 * copies or substantial portions of the Software.
15 *
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22 * SOFTWARE.
23 */
24
25#ifndef FBCPP_EXCEPTION_H
26#define FBCPP_EXCEPTION_H
27
28#include "fb-api.h"
29#include <stdexcept>
30#include <string>
31#include <vector>
32#include <cstdint>
33
34
38namespace fbcpp
39{
40 class Client;
41}
42
43namespace fbcpp::impl
44{
45 class StatusWrapper : public fb::IStatusImpl<StatusWrapper, StatusWrapper>
46 {
47 public:
48 explicit StatusWrapper(Client& client, IStatus* status)
49 : client{&client},
50 status{status}
51 {
52 }
53
54 public:
55 static void checkException(StatusWrapper* status);
56
57 static void catchException(IStatus* status) noexcept;
58
59 static void clearException(StatusWrapper* status) noexcept
60 {
61 status->clearException();
62 }
63
64 void clearException()
65 {
66 if (dirty)
67 {
68 dirty = false;
69 status->init();
70 }
71 }
72
73 bool isDirty() const noexcept
74 {
75 return dirty;
76 }
77
78 bool hasData() const noexcept
79 {
80 return getState() & IStatus::STATE_ERRORS;
81 }
82
83 bool isEmpty() const noexcept
84 {
85 return !hasData();
86 }
87
88 static void setVersionError(
89 IStatus* status, const char* interfaceName, uintptr_t currentVersion, uintptr_t expectedVersion) noexcept
90 {
91 // clang-format off
92 const intptr_t codes[] = {
93 isc_arg_gds, isc_interface_version_too_old,
94 isc_arg_number, (intptr_t) expectedVersion,
95 isc_arg_number, (intptr_t) currentVersion,
96 isc_arg_string, (intptr_t) interfaceName,
97 isc_arg_end,
98 };
99 // clang-format on
100
101 status->setErrors(codes);
102 }
103
104 public:
105 void dispose() noexcept override
106 {
107 // Disposes only the delegated status. Let the user destroy this instance.
108 status->dispose();
109 status = nullptr;
110 }
111
112 void init() noexcept override
113 {
114 clearException();
115 }
116
117 unsigned getState() const noexcept override
118 {
119 return dirty ? status->getState() : 0;
120 }
121
122 void setErrors2(unsigned length, const intptr_t* value) noexcept override
123 {
124 dirty = true;
125 status->setErrors2(length, value);
126 }
127
128 void setWarnings2(unsigned length, const intptr_t* value) noexcept override
129 {
130 dirty = true;
131 status->setWarnings2(length, value);
132 }
133
134 void setErrors(const intptr_t* value) noexcept override
135 {
136 dirty = true;
137 status->setErrors(value);
138 }
139
140 void setWarnings(const intptr_t* value) noexcept override
141 {
142 dirty = true;
143 status->setWarnings(value);
144 }
145
146 const intptr_t* getErrors() const noexcept override
147 {
148 return dirty ? status->getErrors() : cleanStatus();
149 }
150
151 const intptr_t* getWarnings() const noexcept override
152 {
153 return dirty ? status->getWarnings() : cleanStatus();
154 }
155
156 IStatus* clone() const noexcept override
157 {
158 return status->clone();
159 }
160
161 protected:
162 Client* client;
163 IStatus* status;
164 bool dirty = false;
165
166 static const intptr_t* cleanStatus() noexcept
167 {
168 static intptr_t clean[3] = {1, 0, 0};
169 return clean;
170 }
171 };
172} // namespace fbcpp::impl
173
174
178namespace fbcpp
179{
183 class FbCppException : public std::runtime_error
184 {
185 public:
186 using std::runtime_error::runtime_error;
187
191 explicit FbCppException(const std::string& message)
192 : std::runtime_error{message}
193 {
194 }
195 };
196
201 {
202 public:
206 explicit DatabaseException(Client& client, const std::intptr_t* statusVector)
207 : FbCppException{buildMessage(client, statusVector)},
208 sqlState{extractSqlState(statusVector)}
209 {
210 copyErrorVector(statusVector);
211 }
212
214 : FbCppException{static_cast<const FbCppException&>(other)},
215 errorVector{other.errorVector},
216 errorStrings{other.errorStrings},
217 sqlState{other.sqlState}
218 {
219 fixupStringPointers();
220 }
221
222 DatabaseException(DatabaseException&&) = default;
223
224 DatabaseException& operator=(const DatabaseException&) = delete;
225 DatabaseException& operator=(DatabaseException&&) = delete;
226
231 const std::vector<std::intptr_t>& getErrors() const noexcept
232 {
233 return errorVector;
234 }
235
239 std::intptr_t getErrorCode() const noexcept
240 {
241 if (errorVector.size() >= 2 && errorVector[0] == isc_arg_gds)
242 return errorVector[1];
243 return 0;
244 }
245
250 const std::string& getSqlState() const noexcept
251 {
252 return sqlState;
253 }
254
255 private:
256 static std::string buildMessage(Client& client, const std::intptr_t* statusVector);
257 static std::string extractSqlState(const std::intptr_t* statusVector);
258
259 void copyErrorVector(const std::intptr_t* statusVector);
260 void fixupStringPointers();
261
262 private:
263 std::vector<std::intptr_t> errorVector;
264 std::vector<std::string> errorStrings;
265 std::string sqlState;
266 };
267} // namespace fbcpp
268
269
270#endif // FBCPP_EXCEPTION_H
Represents a Firebird client library instance.
Definition Client.h:53
Exception thrown when a Firebird database operation fails.
Definition Exception.h:201
const std::vector< std::intptr_t > & getErrors() const noexcept
Returns the Firebird error vector.
Definition Exception.h:231
std::intptr_t getErrorCode() const noexcept
Returns the primary ISC error code (first isc_arg_gds value), or 0 if none.
Definition Exception.h:239
DatabaseException(Client &client, const std::intptr_t *statusVector)
Constructs a DatabaseException from a Firebird status vector.
Definition Exception.h:206
const std::string & getSqlState() const noexcept
Returns the SQL state string (e.g.
Definition Exception.h:250
Base exception class for all fb-cpp exceptions.
Definition Exception.h:184
FbCppException(const std::string &message)
Constructs an FbCppException with the specified error message.
Definition Exception.h:191
fb-cpp namespace.
Definition Attachment.h:42