26#include "Transaction.h"
27#include "Attachment.h"
31using namespace fbcpp::impl;
36 : attachment{&attachment},
37 statusWrapper{attachment.getClient()},
38 calendarConverter{attachment.getClient()},
39 numericConverter{attachment.getClient()}
44 unsigned flags = fb::IStatement::PREPARE_PREFETCH_METADATA;
47 flags |= fb::IStatement::PREPARE_PREFETCH_LEGACY_PLAN;
50 flags |= fb::IStatement::PREPARE_PREFETCH_DETAILED_PLAN;
52 statementHandle.reset(attachment.
getHandle()->prepare(&statusWrapper, transaction.
getHandle().get(),
56 statementHandle->setCursorName(&statusWrapper, options.
getCursorName()->c_str());
59 cursorFlags = fb::IStatement::CURSOR_TYPE_SCROLLABLE;
61 type =
static_cast<StatementType>(statementHandle->getType(&statusWrapper));
67 throw FbCppException(
"Cannot use SET TRANSACTION command with Statement class. Use Transaction class");
72 "Cannot use COMMIT command with Statement class. Use the commit method from the Transaction class");
77 "Cannot use ROLLBACK command with Statement class. Use the rollback method from the Transaction class");
81 throw FbCppException(
"Unsupported statement type: BLOB segment operations");
88 std::vector<std::byte>& message)
93 message.resize(
metadata->getMessageLength(&statusWrapper));
97 const auto count =
metadata->getCount(&statusWrapper);
98 descriptors.reserve(count);
100 for (
unsigned index = 0
u; index < count; ++index)
105 .scale =
metadata->getScale(&statusWrapper, index),
106 .length =
metadata->getLength(&statusWrapper, index),
109 .isNullable =
static_cast<bool>(
metadata->isNullable(&statusWrapper, index)),
110 .name =
metadata->getField(&statusWrapper, index),
111 .relation =
metadata->getRelation(&statusWrapper, index),
112 .alias =
metadata->getAlias(&statusWrapper, index),
113 .owner =
metadata->getOwner(&statusWrapper, index),
114 .charSetId =
metadata->getCharSet(&statusWrapper, index),
115 .subType =
metadata->getSubType(&statusWrapper, index),
162 message.resize(
metadata->getMessageLength(&statusWrapper));
164 for (
unsigned index = 0
u; index < count; ++index)
175 inMetadata.reset(statementHandle->getInputMetadata(&statusWrapper));
178 outMetadata.reset(statementHandle->getOutputMetadata(&statusWrapper));
181 outRow = std::make_unique<Row>(attachment.
getClient(), outDescriptors, std::span{outMessage});
185 : attachment{o.attachment},
186 statusWrapper{std::move(o.statusWrapper)},
187 calendarConverter{std::move(o.calendarConverter)},
188 numericConverter{std::move(o.numericConverter)},
189 statementHandle{std::move(o.statementHandle)},
190 resultSetHandle{std::move(o.resultSetHandle)},
191 inMetadata{std::move(o.inMetadata)},
192 inDescriptors{std::move(o.inDescriptors)},
193 inMessage{std::move(o.inMessage)},
194 outMetadata{std::move(o.outMetadata)},
195 outDescriptors{std::move(o.outDescriptors)},
196 outMessage{std::move(o.outMessage)},
197 outRow{std::make_unique<Row>(attachment->getClient(), outDescriptors, std::span{outMessage})},
199 cursorFlags{o.cursorFlags}
208 attachment = o.attachment;
209 statusWrapper = std::move(o.statusWrapper);
210 calendarConverter = std::move(o.calendarConverter);
211 numericConverter = std::move(o.numericConverter);
212 statementHandle = std::move(o.statementHandle);
213 resultSetHandle = std::move(o.resultSetHandle);
214 inMetadata = std::move(o.inMetadata);
215 inDescriptors = std::move(o.inDescriptors);
216 inMessage = std::move(o.inMessage);
217 outMetadata = std::move(o.outMetadata);
218 outDescriptors = std::move(o.outDescriptors);
219 outMessage = std::move(o.outMessage);
220 outRow = std::make_unique<Row>(attachment->getClient(), outDescriptors, std::span{outMessage});
222 cursorFlags = o.cursorFlags;
236 resultSetHandle->close(&statusWrapper);
237 resultSetHandle.reset();
240 statementHandle->free(&statusWrapper);
241 statementHandle.reset();
248 return statementHandle->getPlan(&statusWrapper,
false);
255 return statementHandle->getPlan(&statusWrapper,
true);
265 resultSetHandle->close(&statusWrapper);
266 resultSetHandle.reset();
281 resultSetHandle.reset(statementHandle->openCursor(&statusWrapper, transaction.
getHandle().get(),
282 inMetadata.get(), inMessage.data(), outMetadata.get(), cursorFlags));
283 return resultSetHandle->fetchNext(&statusWrapper,
outMessageData) == fb::IStatus::RESULT_OK;
286 statementHandle->execute(&statusWrapper, transaction.
getHandle().get(), inMetadata.get(), inMessage.data(),
292Client& Statement::getClient() noexcept
301 return resultSetHandle && resultSetHandle->fetchNext(&statusWrapper, outMessage.data()) == fb::IStatus::RESULT_OK;
308 return resultSetHandle && resultSetHandle->fetchPrior(&statusWrapper, outMessage.data()) == fb::IStatus::RESULT_OK;
315 return resultSetHandle && resultSetHandle->fetchFirst(&statusWrapper, outMessage.data()) == fb::IStatus::RESULT_OK;
322 return resultSetHandle && resultSetHandle->fetchLast(&statusWrapper, outMessage.data()) == fb::IStatus::RESULT_OK;
329 return resultSetHandle &&
330 resultSetHandle->fetchAbsolute(&statusWrapper,
static_cast<int>(
position), outMessage.data()) ==
331 fb::IStatus::RESULT_OK;
338 return resultSetHandle &&
339 resultSetHandle->fetchRelative(&statusWrapper, offset, outMessage.data()) == fb::IStatus::RESULT_OK;
Represents a connection to a Firebird database.
Client & getClient() noexcept
Returns the Client object reference used to create this Attachment object.
FbRef< fb::IAttachment > getHandle() noexcept
Returns the internal Firebird IAttachment handle.
bool isValid() noexcept
Returns whether the Attachment object is valid.
Represents a Firebird client library instance.
Base exception class for all fb-cpp exceptions.
Reference-counted smart pointer for Firebird objects using addRef/release semantics.
Represents options used when preparing a Statement.
const std::optional< std::string > & getCursorName() const
Returns the cursor name to be set for the statement.
unsigned getDialect() const
Returns the SQL dialect used when preparing the statement.
bool getPrefetchPlan() const
Reports whether the structured plan should be prefetched during prepare.
bool getPrefetchLegacyPlan() const
Reports whether the legacy textual plan should be prefetched during prepare.
CursorType getCursorType() const
Returns the cursor type to be used when opening a result set.
Prepares, executes, and fetches SQL statements against a Firebird attachment.
bool fetchAbsolute(unsigned position)
Positions the cursor on the given absolute row number.
bool fetchRelative(int offset)
Moves the cursor by the requested relative offset.
std::string getLegacyPlan()
Retrieves the textual legacy plan if the server produced one.
void free()
Releases the prepared handle and any associated result set.
bool isValid() noexcept
Returns whether the Statement object is valid.
T get()
Retrieves all output columns into a user-defined aggregate struct.
Statement & operator=(Statement &&o) noexcept
Transfers ownership of another prepared statement into this one.
std::string getPlan()
Retrieves the structured textual plan if the server produced one.
bool fetchNext()
Fetches the next row in the current result set.
bool fetchLast()
Positions the cursor on the last row.
bool execute(Transaction &transaction)
Executes a prepared statement using the supplied transaction.
Statement(Attachment &attachment, Transaction &transaction, std::string_view sql, const StatementOptions &options={})
Prepares an SQL statement.
bool fetchPrior()
Fetches the previous row in the current result set.
bool fetchFirst()
Positions the cursor on the first row.
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.
@ SCROLLABLE
Allows bidirectional traversal and absolute/relative positioning.
DescriptorAdjustedType
Descriptor adjusted type.
@ TIME_TZ
Time of day with time zone.
@ STRING
String type (variable-length).
@ TIMESTAMP_TZ
Timestamp with time zone.
StatementType
Distinguishes the semantic category of the prepared SQL statement.
@ PUT_SEGMENT
Statement writes a blob segment - legacy feature.
@ COMMIT
Statement commits a transaction.
@ ROLLBACK
Statement rolls back a transaction.
@ GET_SEGMENT
Statement reads a blob segment - legacy feature.
@ SELECT
Server classified the statement as a SELECT.
@ START_TRANSACTION
Statement starts a new transaction.
@ SELECT_FOR_UPDATE
Cursor-based SELECT that allows updates.
DescriptorOriginalType
Descriptor original type.
@ TIMESTAMP_TZ_EX
Extended timestamp with time zone.
@ TIME_TZ_EX
Extended time of day with time zone.
Describes a parameter or column.
DescriptorOriginalType originalType
Original SQL type as reported by Firebird.