feat: support Firebird BLOB seek in proxy#39081
Conversation
|
I've also been working on BLOB support in the Firebird proxy (#39050). The original issue only covered 1. The deferred BLOB handle Jaybird 5.0.7+ pipelines BLOB operations: it sends
Reproducible with Jaybird 5.0.10: INSERT stores empty BLOBs, and a subsequent SELECT of a BLOB column hangs. 2. The The response data must be Reproducible with Jaybird 5.0.6 by reading back a 21-byte BLOB (2 + 21 = 23 bytes of payload, 3 bytes of padding, declared length 26). Segments whose length % 4 == 0 or 2 survive by luck — that's why small ASCII test payloads often pass. Large BLOBs always fail: the client requests chunks of 32765 bytes (32765 % 4 == 1). |
Thank you very much, I will make corrections |
…e 'op_get_segment' response
|
Thank you very much for this detailed report — both bugs have been reproduced on my end and have now been fixed. 1. Unresolved delay handle '0xFFFF' Root cause: Both 'FirebirdCreateBlobCommandExecutor' and 'FirebirdOpenBlobCommandExecutor' generate a new handle and return immediately, but neither records the handle for subsequent operations. When Jaybird uses '0xFFFF' to pipeline before the response returns, all subsequent executors (put-segment, get-segment, seek, close, cancel) directly look for '0xFFFF' and get an empty value—causing silent drops (data) during writing and deadlocks when reading. Fix: 'FirebirdBlobRegistry' now tracks the last created/opened blob handle by connection. 'create_blob2' and 'open_blob2' are both recorded using 'setLastBlobHandle()'. All five subsequent executors now call 'resolveBlobHandle()' before each registry/cache lookup, and when the client sends '0xFFFF', it returns the last handle—which matches how a real Firebird server replaces the recently created object handle. 2. Incorrect fill length in the 'op_get_segment' response Root cause: 'FirebirdGetBlobSegmentResponsePacket.write()' adds its own internal 4-byte alignment padding after a 2-byte prefix. Because 'FirebirdGenericResponsePacket' encapsulates response data with its XDR length prefix, the internal padding is included in that length. For a 21-byte fragment: declared length = 2 + 21 + 3 (padded) = 26, so Jaybird reads the 21-byte data and interprets the 3 padding bytes as the prefix -> for the next 2-byte fragment length, causing buffer overrun. Fix: Removed internal padding from 'FirebirdGetBlobSegmentResponsePacket.write()'. The generic response encapsulation has applied the correct external alignment via '(4 - length) & 3', which lies outside the declared data length, which is exactly what the protocol requires. Now, both fixes include dedicated unit tests, such as the 'assertExecuteWithDeferredHandle' test, which verifies '0xFFFF' parsing on all five subsequent executors, as well as updated response packet tests for misaligned fragments. If you wish to coordinate BLOB testing between these two PRs, I am happy to help. |
Special note: Since there are many design changes this time, I sincerely hope someone will carefully review this PR. Thx😘
Fixes #39051.
Changes proposed in this pull request:
OPEN_BLOBregister content and cursor state.SEEK_BLOBreturn the resulting cursor position.GET_SEGMENTread from the current cursor and return EOF correctly.INFO_BLOBread the current BLOB length from the same state.Validation:
./mvnw -pl database/protocol/dialect/firebird -am -Dspotless.skip=true -Dtest=FirebirdBlobRegistryTest,FirebirdBlobInfoReturnPacketTest -Dsurefire.failIfNoSpecifiedTests=false test./mvnw -pl proxy/frontend/dialect/firebird -am -DskipITs -Dspotless.skip=true -Djacoco.skip=true -Dtest=FirebirdOpenBlobCommandExecutorTest,FirebirdCloseBlobCommandExecutorTest,FirebirdCancelBlobCommandExecutorTest,FirebirdGetBlobSegmentCommandExecutorTest,FirebirdSeekBlobCommandExecutorTest,FirebirdBlobInfoExecutorTest,FirebirdFrontendEngineTest,FirebirdAuthenticationEngineTest,FirebirdCommandExecuteEngineTest -Dsurefire.failIfNoSpecifiedTests=false -DargLine='-javaagent:/Users/didi/.m2/repository/net/bytebuddy/byte-buddy-agent/1.18.10/byte-buddy-agent-1.18.10.jar -Djdk.attach.allowAttachSelf=true -XX:+EnableDynamicAgentLoading' test./mvnw spotless:apply -Pcheck -T1C./mvnw checkstyle:check -Pcheck -T1C