26#include "Attachment.h"
29#include "Transaction.h"
32using namespace fbcpp::impl;
39 statusWrapper{client},
40 handle{std::move(handle)}
46 statusWrapper{std::move(o.statusWrapper)},
47 handle{std::move(o.handle)}
53 return handle->getSize(&statusWrapper);
58 return handle->getState(&statusWrapper, pos);
63 const auto result = handle->findError(&statusWrapper, pos);
65 if (result == fb::IBatchCompletionState::NO_MORE_ERRORS)
75 handle->getStatus(&statusWrapper, tempStatus.get(), pos);
77 std::vector<std::intptr_t> result;
78 const auto* errors = tempStatus->getErrors();
82 const auto* p = errors;
84 while (*p != isc_arg_end)
86 result.push_back(*p++);
87 result.push_back(*p++);
90 result.push_back(isc_arg_end);
100 : client{&statement.getAttachment().getClient()},
101 transaction{&transaction},
102 statement{&statement},
103 statusWrapper{*client}
108 const auto parBlock = buildParametersBlock(options);
111 &statusWrapper, statement.
getInputMetadata().get(),
static_cast<unsigned>(parBlock.size()), parBlock.data()));
116 : client{&attachment.getClient()},
117 transaction{&transaction},
118 statusWrapper{*client}
123 const auto parBlock = buildParametersBlock(options);
125 handle.reset(attachment.
getHandle()->createBatch(&statusWrapper, transaction.
getHandle().get(),
126 static_cast<unsigned>(sql.length()), sql.data(), dialect,
nullptr,
static_cast<unsigned>(parBlock.size()),
132 transaction{o.transaction},
133 statement{o.statement},
134 statusWrapper{std::move(o.statusWrapper)},
135 handle{std::move(o.handle)}
145 handle->add(&statusWrapper, count, inBuffer);
162 const auto preparedBpb = prepareBpb(bpb);
165 handle->addBlob(&statusWrapper,
static_cast<unsigned>(data.size()), data.data(), &blobId.
id,
166 static_cast<unsigned>(preparedBpb.size()), preparedBpb.data());
174 handle->appendBlobData(&statusWrapper,
static_cast<unsigned>(data.size()), data.data());
180 handle->addBlobStream(&statusWrapper,
static_cast<unsigned>(data.size()), data.data());
188 handle->registerBlob(&statusWrapper, &existingBlob.
id, &batchId.
id);
197 const auto preparedBpb = prepareBpb(bpb);
198 handle->setDefaultBpb(&statusWrapper,
static_cast<unsigned>(preparedBpb.size()), preparedBpb.data());
204 return handle->getBlobAlignment(&statusWrapper);
214 auto completionState =
fbUnique(handle->execute(&statusWrapper, transaction->
getHandle().get()));
222 handle->cancel(&statusWrapper);
229 handle->close(&statusWrapper);
238 metadata.reset(handle->getMetadata(&statusWrapper));
247 if (inputDescriptors.empty())
248 buildInputDescriptors();
250 return inputDescriptors;
256std::vector<std::uint8_t> Batch::buildParametersBlock(
const BatchOptions& options)
258 auto builder =
fbUnique(client->
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::BATCH,
nullptr, 0));
261 builder->insertInt(&statusWrapper, fb::IBatch::TAG_MULTIERROR, 1);
264 builder->insertInt(&statusWrapper, fb::IBatch::TAG_RECORD_COUNTS, 1);
267 builder->insertInt(&statusWrapper, fb::IBatch::TAG_BUFFER_BYTES_SIZE,
static_cast<int>(bufferSize.value()));
270 builder->insertInt(&statusWrapper, fb::IBatch::TAG_BLOB_POLICY,
static_cast<int>(options.
getBlobPolicy()));
275 &statusWrapper, fb::IBatch::TAG_DETAILED_ERRORS,
static_cast<int>(options.
getDetailedErrors()));
278 const auto buffer = builder->getBuffer(&statusWrapper);
279 const auto length = builder->getBufferLength(&statusWrapper);
281 return {buffer, buffer + length};
284std::vector<std::uint8_t> Batch::prepareBpb(
const BlobOptions& bpb)
286 auto builder =
fbUnique(client->
getUtil()->getXpbBuilder(&statusWrapper, fb::IXpbBuilder::BPB,
287 reinterpret_cast<const std::uint8_t*
>(bpb.
getBpb().data()),
static_cast<unsigned>(bpb.
getBpb().size())));
289 if (
const auto type = bpb.
getType(); type.has_value())
290 builder->insertInt(&statusWrapper, isc_bpb_type,
static_cast<int>(type.value()));
292 if (
const auto storage = bpb.
getStorage(); storage.has_value())
293 builder->insertInt(&statusWrapper, isc_bpb_storage,
static_cast<int>(storage.value()));
295 const auto buffer = builder->getBuffer(&statusWrapper);
296 const auto length = builder->getBufferLength(&statusWrapper);
298 return {buffer, buffer + length};
301void Batch::buildInputDescriptors()
304 const auto count = metadata->getCount(&statusWrapper);
306 inputDescriptors.reserve(count);
308 for (
unsigned index = 0u; index < count; ++index)
313 .scale = metadata->getScale(&statusWrapper, index),
314 .length = metadata->getLength(&statusWrapper, index),
315 .offset = metadata->getOffset(&statusWrapper, index),
316 .nullOffset = metadata->getNullOffset(&statusWrapper, index),
317 .isNullable =
static_cast<bool>(metadata->isNullable(&statusWrapper, index)),
318 .name = metadata->getField(&statusWrapper, index),
319 .relation = metadata->getRelation(&statusWrapper, index),
320 .alias = metadata->getAlias(&statusWrapper, index),
321 .owner = metadata->getOwner(&statusWrapper, index),
322 .charSetId = metadata->getCharSet(&statusWrapper, index),
323 .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.