Skip to content

Add Batch Execution support (IBatch wrapper) (#26)#40

Open
fdcastel wants to merge 3 commits intoasfernandes:mainfrom
fdcastel:issue-26-pr
Open

Add Batch Execution support (IBatch wrapper) (#26)#40
fdcastel wants to merge 3 commits intoasfernandes:mainfrom
fdcastel:issue-26-pr

Conversation

@fdcastel
Copy link
Contributor

Fixes #26

Summary

Adds a new Batch class that wraps the Firebird IBatch interface, enabling
bulk DML operations (INSERT/UPDATE/DELETE) with a single server round-trip.
This is the primary performance path for ETL workloads against Firebird 4.0+
and maps directly to ODBC's "array of parameter values" feature
(SQL_ATTR_PARAMSET_SIZE > 1).

New types

Type Purpose
BlobPolicy Enum for blob handling modes: NONE, ID_ENGINE, ID_USER, STREAM
BatchOptions Fluent builder for batch parameters (multi-error, record counts, buffer size, blob policy, detailed errors)
BatchCompletionState RAII wrapper around IBatchCompletionState — provides per-message execution results, error lookup, and detailed error status
Batch RAII wrapper around IBatch — collects messages and executes them in bulk

Creation paths

Two constructors for Batch:

  1. From a prepared Statement — uses IStatement::createBatch(). Enables
    the convenience addMessage() method that copies the Statement's current
    input-message buffer into the batch.
  2. From an Attachment + SQL text — uses IAttachment::createBatch().
    Messages are added via the raw add() method.

API overview

// Prepare a statement and create a batch
Statement insert{attachment, transaction, "insert into t (id, name) values (?, ?)"};
Batch batch{insert, transaction, BatchOptions().setRecordCounts(true)};

// Add messages using Statement's type-safe setters
insert.setInt32(0, 1);
insert.setString(1, "Alice");
batch.addMessage();

insert.setInt32(0, 2);
insert.setString(1, "Bob");
batch.addMessage();

// Execute and inspect results
auto completionState = batch.execute();
assert(completionState.getSize() == 2);
assert(completionState.getState(0) == 1);  // 1 row affected

Blob support

  • addBlob() — inline blob with engine-generated or user-generated ID
  • appendBlobData() — append to the last inline blob
  • addBlobStream() — stream-mode blob data
  • registerBlob() — register an existing Blob for batch use
  • setDefaultBpb() — set default blob parameter block
  • getBlobAlignment() — query alignment requirement

Minor additions to Statement

  • getAttachment() — returns the Attachment& used to create the statement
  • getInputMessage() — provides access to the raw input message buffer (used
    by Batch::addMessage())

Files changed

File Change
src/fb-cpp/Batch.h New — BlobPolicy, BatchOptions, BatchCompletionState, Batch
src/fb-cpp/Batch.cpp New — implementation
src/test/Batch.cpp New — 9 test cases
src/fb-cpp/Statement.h Added getAttachment() and getInputMessage() accessors
src/fb-cpp/fb-cpp.h Added #include "Batch.h"

Test cases

Test What it verifies
constructorFromStatementAndExecute Statement-based batch with addMessage(), record counts, data verification
constructorFromAttachmentAndExecute Attachment-based batch with raw add(), metadata-driven message building
moveConstructorTransfersOwnership Move semantics invalidate the source
executeReportsNoInfoWhenRecordCountsDisabled SUCCESS_NO_INFO when record counts are off
executeWithBadDataReportsExecuteFailed Duplicate PK → EXECUTE_FAILED, findError() locates the failure, multi-error allows partial success
cancelDiscardsMessages cancel() invalidates the handle, nothing is inserted
blobWithIdEngine Inline blob via addBlob() with BlobPolicy::ID_ENGINE, content verified
registerExistingBlob Pre-created Blob registered in batch via registerBlob(), content verified
closeReleasesHandle close() invalidates the handle

Design notes

  • Follows the existing RAII patterns used by Blob, Statement, and Transaction.
  • BatchCompletionState::findError() returns std::optional<unsigned> instead
    of the raw 0xFFFFFFFF sentinel — idiomatic modern C++.
  • BatchCompletionState is disposable (not reference-counted), so the handle
    is held via FbUniquePtr and disposed in the destructor.
  • Batch holds a FbRef<fb::IBatch> (reference-counted) consistent with how
    Statement holds its IStatement handle.
  • IBatch requires Firebird 4.0+. On older servers, createBatch() will throw
    a DatabaseException.

Add Batch, BatchOptions, BatchCompletionState, and BlobPolicy types
that wrap the Firebird IBatch interface for bulk DML operations.

Two creation paths:
- From a prepared Statement (IStatement::createBatch)
- From an Attachment + SQL text (IAttachment::createBatch)

Also adds getAttachment() and getInputMessage() accessors to Statement.
Copy link
Owner

@asfernandes asfernandes left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I do want more time to review the interfaces.
Batch is not something I'm very aware and some of the interfaces appears very raw (as native ones) for me.

Add rules from PR asfernandes#40 review:
- Use lowercase suffixes for numeric literals (1u, not 1U)
- Do not use string literals in assert() expressions
- Do not explicitly define destructor as = default unless necessary
- Prefer vector iterator-range constructor over allocate + memcpy
- Remove string literal from assert() expression
- Fix brace style: remove braces from single-line if, add braces to multi-line if
- Use vector iterator-range constructor instead of allocate + memcpy
- Remove unnecessary explicit default destructor on BatchCompletionState
- Rename getMetadata() to getInputMetadata() for consistency with Statement
- Add getInputDescriptors() with lazy descriptor caching
- Fix numeric suffix casing: U -> u in all test assertions
@fdcastel
Copy link
Contributor Author

Requested changes pushed.

I also took the liberty of updating AGENTS.md in a separate commit. Feel free to ignore or modify those updates as needed.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Support for Batch Execution (IBatch)

2 participants