fb-cpp 0.0.2
A modern C++ wrapper for the Firebird database API
Loading...
Searching...
No Matches
Request.cpp
1/*
2 * MIT License
3 *
4 * Copyright (c) 2026 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#include "Request.h"
26#include "../Attachment.h"
27#include "../Transaction.h"
28#include <algorithm>
29#include <cassert>
30
32{
33 Request::Request(Attachment& a, std::span<const std::byte> blr, const std::vector<MessageEntry>& entries)
34 : attachment{&a},
35 statusWrapper{a.getClient()}
36 {
37 assert(attachment->isValid());
38
39 for (const auto& entry : entries)
40 {
41 if (entry.messageNumber > 255u)
42 throw FbCppException("Message number must be between 0 and 255");
43
44 const auto it = std::lower_bound(messages.begin(), messages.end(), entry.messageNumber,
45 [](const auto& pair, unsigned number) { return pair.first < number; });
46
47 if (it != messages.end() && it->first == entry.messageNumber)
48 throw FbCppException("Duplicated message number " + std::to_string(entry.messageNumber));
49
50 messages.emplace(it, entry.messageNumber, RequestMessage{attachment->getClient(), entry.format});
51 }
52
53 handle.reset(attachment->getHandle()->compileRequest(
54 &statusWrapper, static_cast<unsigned>(blr.size()), reinterpret_cast<const unsigned char*>(blr.data())));
55 }
56
58 : attachment{o.attachment},
59 messages{std::move(o.messages)},
60 statusWrapper{std::move(o.statusWrapper)},
61 handle{std::move(o.handle)}
62 {
63 }
64
66 {
67 if (this != &o)
68 {
69 attachment = o.attachment;
70 messages = std::move(o.messages);
71 statusWrapper = std::move(o.statusWrapper);
72 handle = std::move(o.handle);
73 }
74
75 return *this;
76 }
77
78 RequestMessage& Request::getMessage(unsigned messageNumber)
79 {
80 const auto message = findMessage(messageNumber);
81
82 if (!message)
83 {
84 throw FbCppException(
85 "Message number " + std::to_string(messageNumber) + " was not declared in the request");
86 }
87
88 return *message;
89 }
90
92 {
93 assert(isValid());
94
95 handle->free(&statusWrapper);
96 handle.reset();
97 }
98
99 void Request::start(Transaction& transaction, unsigned level)
100 {
101 assert(isValid());
102 assert(transaction.isValid());
103
104 handle->start(&statusWrapper, transaction.getHandle().get(), static_cast<int>(level));
105 }
106
107 void Request::startAndSend(Transaction& transaction, unsigned messageNumber, unsigned level)
108 {
109 assert(isValid());
110 assert(transaction.isValid());
111
112 const auto message = findMessage(messageNumber);
113
114 if (!message)
115 {
116 throw FbCppException(
117 "Message number " + std::to_string(messageNumber) + " was not declared in the request");
118 }
119
120 handle->startAndSend(&statusWrapper, transaction.getHandle().get(), static_cast<int>(level), messageNumber,
121 static_cast<unsigned>(message->message.size()), message->message.data());
122 }
123
124 void Request::send(unsigned messageNumber, unsigned level)
125 {
126 assert(isValid());
127
128 const auto message = findMessage(messageNumber);
129
130 if (!message)
131 {
132 throw FbCppException(
133 "Message number " + std::to_string(messageNumber) + " was not declared in the request");
134 }
135
136 handle->send(&statusWrapper, static_cast<int>(level), messageNumber,
137 static_cast<unsigned>(message->message.size()), message->message.data());
138 }
139
140 bool Request::receive(unsigned messageNumber, unsigned level)
141 {
142 assert(isValid());
143
144 const auto message = findMessage(messageNumber);
145
146 if (!message)
147 {
148 throw FbCppException(
149 "Message number " + std::to_string(messageNumber) + " was not declared in the request");
150 }
151
152 try
153 {
154 handle->receive(&statusWrapper, static_cast<int>(level), messageNumber,
155 static_cast<unsigned>(message->message.size()), message->message.data());
156 }
157 catch (const DatabaseException& e)
158 {
159 if (e.getErrorCode() == isc_req_sync) // end of records
160 return false;
161
162 throw;
163 }
164
165 return true;
166 }
167
168 void Request::unwind(unsigned level)
169 {
170 assert(isValid());
171
172 handle->unwind(&statusWrapper, static_cast<int>(level));
173 }
174
175 RequestMessage* Request::findMessage(unsigned messageNumber) const noexcept
176 {
177 const auto it = std::lower_bound(messages.begin(), messages.end(), messageNumber,
178 [](const auto& pair, unsigned number) { return pair.first < number; });
179
180 if (it != messages.end() && it->first == messageNumber)
181 return const_cast<RequestMessage*>(&it->second);
182
183 return nullptr;
184 }
185} // namespace fbcpp::request
Represents a connection to a Firebird database.
Definition Attachment.h:220
FbRef< fb::IAttachment > getHandle() noexcept
Returns the internal Firebird IAttachment handle.
Definition Attachment.h:296
bool isValid() noexcept
Returns whether the Attachment object is valid.
Definition Attachment.h:280
Exception thrown when a Firebird database operation fails.
Definition Exception.h:248
std::intptr_t getErrorCode() const noexcept
Returns the primary ISC error code (first isc_arg_gds value), or 0 if none.
Definition Exception.h:286
Base exception class for all fb-cpp exceptions.
Definition Exception.h:231
Represents a transaction in one or more Firebird databases.
bool isValid() noexcept
Returns whether the Transaction object is valid.
FbRef< fb::ITransaction > getHandle() noexcept
Returns the internal Firebird ITransaction handle.
A message buffer of a Firebird request with typed accessors.
Represents a Firebird request: a precompiled BLR (Binary Language Representation) program.
Definition Request.h:68
Request & operator=(Request &&o) noexcept
Move assignment.
Definition Request.cpp:65
void startAndSend(Transaction &transaction, unsigned messageNumber, unsigned level=0)
Starts the execution of the request, sending it an input message.
Definition Request.cpp:107
void send(unsigned messageNumber, unsigned level=0)
Sends an input message to the running request.
Definition Request.cpp:124
void free()
Releases the compiled request.
Definition Request.cpp:91
bool isValid() noexcept
Returns whether the Request object is valid.
Definition Request.h:130
RequestMessage & getMessage(unsigned messageNumber)
Returns the message associated with a message number declared at construction time.
Definition Request.cpp:78
Request(Attachment &attachment, std::span< const std::byte > blr, const std::vector< MessageEntry > &messages={})
Compiles a request from the given BLR for the attachment's database.
Definition Request.cpp:33
void unwind(unsigned level=0)
Unwinds the running request.
Definition Request.cpp:168
bool receive(unsigned messageNumber, unsigned level=0)
Receives a record from the running request into the associated message.
Definition Request.cpp:140
void start(Transaction &transaction, unsigned level=0)
Starts the execution of the request.
Definition Request.cpp:99
fb-cpp request namespace.
Definition Request.cpp:32