26#include "Attachment.h"
29#include "Transaction.h"
32using namespace fbcpp::impl;
39 status{client.newStatus()},
40 statusWrapper{client, status.get()},
41 handle{std::move(handle)}
47 status{std::move(o.status)},
48 statusWrapper{std::move(o.statusWrapper)},
49 handle{std::move(o.handle)}
55 return handle->getSize(&statusWrapper);
60 return handle->getState(&statusWrapper, pos);
65 const auto result = handle->findError(&statusWrapper, pos);
67 if (result == fb::IBatchCompletionState::NO_MORE_ERRORS)
77 handle->getStatus(&statusWrapper, tempStatus.get(), pos);
79 std::vector<std::intptr_t> result;
80 const auto* errors = tempStatus->getErrors();
84 const auto* p = errors;
86 while (*p != isc_arg_end)
88 result.push_back(*p++);
89 result.push_back(*p++);
92 result.push_back(isc_arg_end);
102 : client{&statement.getAttachment().getClient()},
103 transaction{&transaction},
104 statement{&statement},
105 status{client->newStatus()},
106 statusWrapper{*client, status.get()}
111 const auto parBlock = buildParametersBlock(*client, options);
114 &statusWrapper, statement.
getInputMetadata().get(),
static_cast<unsigned>(parBlock.size()), parBlock.data()));
119 : client{&attachment.getClient()},
120 transaction{&transaction},
121 status{client->newStatus()},
122 statusWrapper{*client, status.get()}
127 const auto parBlock = buildParametersBlock(*client, options);
129 handle.reset(attachment.
getHandle()->createBatch(&statusWrapper, transaction.
getHandle().get(),
130 static_cast<unsigned>(sql.length()), sql.data(), dialect,
nullptr,
static_cast<unsigned>(parBlock.size()),
136 transaction{o.transaction},
137 statement{o.statement},
138 status{std::move(o.status)},
139 statusWrapper{std::move(o.statusWrapper)},
140 handle{std::move(o.handle)}
150 handle->add(&statusWrapper, count, inBuffer);
167 const auto preparedBpb = prepareBpb(*client, bpb);
170 handle->addBlob(&statusWrapper,
static_cast<unsigned>(data.size()), data.data(), &blobId.
id,
171 static_cast<unsigned>(preparedBpb.size()), preparedBpb.data());
179 handle->appendBlobData(&statusWrapper,
static_cast<unsigned>(data.size()), data.data());
185 handle->addBlobStream(&statusWrapper,
static_cast<unsigned>(data.size()), data.data());
193 handle->registerBlob(&statusWrapper, &existingBlob.
id, &batchId.
id);
202 const auto preparedBpb = prepareBpb(*client, bpb);
203 handle->setDefaultBpb(&statusWrapper,
static_cast<unsigned>(preparedBpb.size()), preparedBpb.data());
209 return handle->getBlobAlignment(&statusWrapper);
219 auto completionState =
fbUnique(handle->execute(&statusWrapper, transaction->
getHandle().get()));
227 handle->cancel(&statusWrapper);
234 handle->close(&statusWrapper);
243 metadata.reset(handle->getMetadata(&statusWrapper));
252 if (inputDescriptors.empty())
253 buildInputDescriptors();
255 return inputDescriptors;
261std::vector<std::uint8_t> Batch::buildParametersBlock(
Client& client,
const BatchOptions& options)
263 auto builder =
fbUnique(client.
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::BATCH,
nullptr, 0));
266 builder->insertInt(&statusWrapper, fb::IBatch::TAG_MULTIERROR, 1);
269 builder->insertInt(&statusWrapper, fb::IBatch::TAG_RECORD_COUNTS, 1);
272 builder->insertInt(&statusWrapper, fb::IBatch::TAG_BUFFER_BYTES_SIZE,
static_cast<int>(bufferSize.value()));
275 builder->insertInt(&statusWrapper, fb::IBatch::TAG_BLOB_POLICY,
static_cast<int>(options.
getBlobPolicy()));
280 &statusWrapper, fb::IBatch::TAG_DETAILED_ERRORS,
static_cast<int>(options.
getDetailedErrors()));
283 const auto buffer = builder->getBuffer(&statusWrapper);
284 const auto length = builder->getBufferLength(&statusWrapper);
286 return {buffer, buffer + length};
289std::vector<std::uint8_t> Batch::prepareBpb(
Client& client,
const BlobOptions& bpb)
291 auto builder =
fbUnique(client.
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::BPB,
292 reinterpret_cast<const std::uint8_t*
>(bpb.
getBpb().data()),
static_cast<unsigned>(bpb.
getBpb().size())));
294 if (
const auto type = bpb.
getType(); type.has_value())
295 builder->insertInt(&statusWrapper, isc_bpb_type,
static_cast<int>(type.value()));
297 if (
const auto storage = bpb.
getStorage(); storage.has_value())
298 builder->insertInt(&statusWrapper, isc_bpb_storage,
static_cast<int>(storage.value()));
300 const auto buffer = builder->getBuffer(&statusWrapper);
301 const auto length = builder->getBufferLength(&statusWrapper);
303 return {buffer, buffer + length};
306void Batch::buildInputDescriptors()
309 const auto count = metadata->getCount(&statusWrapper);
311 inputDescriptors.reserve(count);
313 for (
unsigned index = 0u; index < count; ++index)
318 .scale = metadata->getScale(&statusWrapper, index),
319 .length = metadata->getLength(&statusWrapper, index),
320 .offset = metadata->getOffset(&statusWrapper, index),
321 .nullOffset = metadata->getNullOffset(&statusWrapper, index),
322 .isNullable =
static_cast<bool>(metadata->isNullable(&statusWrapper, index)),
323 .name = metadata->getField(&statusWrapper, index),
324 .relation = metadata->getRelation(&statusWrapper, index),
325 .alias = metadata->getAlias(&statusWrapper, index),
326 .owner = metadata->getOwner(&statusWrapper, index),
327 .charSetId = metadata->getCharSet(&statusWrapper, index),
328 .subType = metadata->getSubType(&statusWrapper, index),
Represents a connection to a Firebird database.
FbRef< fb::IAttachment > getHandle() noexcept
Returns the internal Firebird IAttachment handle.
bool isValid() noexcept
Returns whether the Attachment object is valid.
Wraps IBatchCompletionState to provide RAII-safe access to batch execution results.
std::optional< unsigned > findError(unsigned pos)
Finds the next error at or after the given position.
int getState(unsigned pos)
Returns the per-message result at the given position.
std::vector< std::intptr_t > getStatus(unsigned pos)
Returns the detailed error status vector for the given position.
BatchCompletionState(Client &client, FbUniquePtr< fb::IBatchCompletionState > handle) noexcept
Constructs a BatchCompletionState from a Firebird completion state handle.
unsigned getSize()
Returns the number of messages processed.
Configuration options for creating a Batch.
std::optional< unsigned > getBufferBytesSize() const
Returns the batch buffer size in bytes, or nullopt for the server default.
bool getRecordCounts() const
Returns whether per-message affected row counts are reported.
unsigned getDetailedErrors() const
Returns the maximum number of detailed error statuses to collect.
BlobPolicy getBlobPolicy() const
Returns the blob handling policy.
bool getMultiError() const
Returns whether multiple errors are collected per execution.
Wraps the Firebird IBatch interface for bulk DML operations.
void close()
Closes the batch handle and releases resources.
void addBlobStream(std::span< const std::byte > data)
Adds blob data in stream mode (BlobPolicy::STREAM only).
bool isValid() const noexcept
Returns whether the batch handle is valid.
void appendBlobData(std::span< const std::byte > data)
Appends more data to the last blob added with addBlob().
void addMessage()
Adds the Statement's current input-message buffer as one message.
void add(unsigned count, const void *inBuffer)
Adds one or more raw messages to the batch buffer.
const std::vector< Descriptor > & getInputDescriptors()
Returns cached input parameter descriptors for this batch.
FbRef< fb::IMessageMetadata > getInputMetadata()
Returns the input metadata for this batch.
BlobId registerBlob(const BlobId &existingBlob)
Registers an existing blob (created via the normal Blob class) for use in the batch,...
void setDefaultBpb(const BlobOptions &bpb)
Sets the default BPB (Blob Parameter Block) for blobs in this batch.
BlobId addBlob(std::span< const std::byte > data, const BlobOptions &bpb={})
Adds an inline blob and returns its batch-local ID.
BatchCompletionState execute()
Executes all queued messages and returns the completion state.
Batch(Statement &statement, Transaction &transaction, const BatchOptions &options={})
Creates a Batch from a prepared Statement.
void cancel()
Cancels the batch, discarding all queued messages.
unsigned getBlobAlignment()
Returns the blob alignment requirement for this batch.
Represents a Firebird blob identifier.
ISC_QUAD id
Stores the raw Firebird blob identifier value.
Additional options used when creating or opening blobs.
const std::optional< BlobType > getType() const
Retrieves the blob type to be used for blob operations.
const std::optional< BlobStorage > getStorage() const
Retrieves the blob storage mode.
const std::vector< std::uint8_t > & getBpb() const noexcept
Retrieves the blob parameter block (BPB) used during blob operations.
Represents a Firebird client library instance.
fb::IUtil * getUtil()
Returns a Firebird IUtil interface.
FbUniquePtr< fb::IStatus > newStatus()
Creates and returns a Firebird IStatus instance.
Reference-counted smart pointer for Firebird objects using addRef/release semantics.
Prepares, executes, and fetches SQL statements against a Firebird attachment.
bool isValid() noexcept
Returns whether the Statement object is valid.
FbRef< fb::IStatement > getStatementHandle() noexcept
Provides direct access to the underlying Firebird statement handle.
FbRef< fb::IMessageMetadata > getInputMetadata() noexcept
Returns the metadata describing prepared input parameters.
std::vector< std::byte > & getInputMessage() noexcept
Provides direct access to the raw input message buffer.
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.
DescriptorAdjustedType
Descriptor adjusted type.
DescriptorOriginalType
Descriptor original type.
FbUniquePtr< T > fbUnique(T *obj) noexcept
Creates a unique pointer for a Firebird disposable object.
@ NONE
Blobs are not allowed in the batch.
std::unique_ptr< T, impl::FbDisposeDeleter > FbUniquePtr
Unique pointer type for Firebird disposable objects.
Describes a parameter or column.
DescriptorOriginalType originalType
Original SQL type as reported by Firebird.