|
| 1 | += jdp-2025-03: Implement Protocol 19 |
| 2 | + |
| 3 | +// SPDX-FileCopyrightText: Copyright 2025 Mark Rotteveel |
| 4 | +// SPDX-License-Identifier: LicenseRef-PDL-1.0 |
| 5 | + |
| 6 | +== Status |
| 7 | + |
| 8 | +* Draft |
| 9 | +* Proposed for: Jaybird 5, Jaybird 6, Jaybird 7 |
| 10 | + |
| 11 | +== Type |
| 12 | + |
| 13 | +* Feature-Specification |
| 14 | + |
| 15 | +== Context |
| 16 | + |
| 17 | +Firebird 5.0.3 introduces protocol version 19, which will provide a significant performance improvement for small blobs. |
| 18 | +This improvement is achieved by sending small blobs inline during the response to cursor fetch, removing the need to explicitly open and request the blobs one by one. |
| 19 | + |
| 20 | +Overview of protocol changes: |
| 21 | + |
| 22 | +* The upper limit for inline blob length is 65535 bytes (0xFFFF); |
| 23 | +this includes segment length(s). |
| 24 | +* `op_execute`/`op_execute2` has an extra (unsigned) int `p_sqldata_inline_blob_size` with the requested inline blob size sent immediately after `p_sqldata_cursor_flags` |
| 25 | +* We don't cover the changes for `op_exec_immediate2` as Jaybird doesn't implement it |
| 26 | +* The response to `op_execute2` will have zero or more `op_inline_blob` (114) responses before the `op_sql_response` packet |
| 27 | +* The response to `op_fetch` will have zero or more `op_inline_blob` (114) responses before each `op_fetch_response` |
| 28 | +* The `op_line_blob` response is the `P_INLINE_BLOB` message with the following payload: |
| 29 | +** `p_tran_id` int (formally short): transaction handle |
| 30 | +** `p_blob_id` long: blob id |
| 31 | +** `p_blob_info` buffer: blob info with (`isc_info_blob_num_segments`, `isc_info_blob_max_segment`, `isc_info_blob_total_length`, `isc_info_blob_type`, `isc_info_end`) |
| 32 | +** `p_blob_data` buffer: blob data (including segment lengths!) |
| 33 | +* Two DPB items were added, `isc_dpb_max_blob_cache_size` (159) and `isc_dpb_max_inline_blob_size` (160), which are used to configure the client. |
| 34 | + |
| 35 | +The JDBC implementation in Jaybird requests blobs with a blob parameter buffer that should match the "`normal`" blob, but API-wise on the `FbDatabase` side, it could be anything. |
| 36 | + |
| 37 | +== Decision |
| 38 | + |
| 39 | +As Jaybird 5 is the "`long-term support`" version for Java 8, and this is a considerable improvement, implementation of protocol version 19 will be done in Jaybird 5, Jaybird 6, and Jaybird 7. |
| 40 | + |
| 41 | +=== Decision details |
| 42 | + |
| 43 | +* Two connection properties, `maxBlobCacheSize` and `maxInlineBlobSize`, are added and associated with their respective DPB items. |
| 44 | +That way the implementation will also support configuring inline blobs for native connections (when using fbclient 5.0.3 or higher). |
| 45 | +** If `maxInlineBlobSize` is not explicitly set, it will use a default of 64 KiB for pure Java connections; |
| 46 | +for native connections, it will use the fbclient default (currently also 64 KiB). + |
| 47 | +** Setting `maxInlineBlobSize` to `0` will disable inline blobs |
| 48 | +** If `maxBlobCacheSize` is not explicit set, it will use a default of 10 MiB for pure Java connections; |
| 49 | +for native connections, it will use the fbclient default (currently also 10 MiB). |
| 50 | +** Setting `maxBlobCacheSize` to `0` will *not* disable inline blobs. |
| 51 | +* The received inline blobs will be registered on the `FbWireDatabase` instance in a blob cache, to be returned from `createBlobForInput` as an inline blob instance implementing `FbWireBlob`. |
| 52 | +** The blob cache tracks memory use based on the blob length and will hold the blob data *without* segment lengths. |
| 53 | +If the blob cache exceeds the `maxInlineBlobSize`, the inline blob will be thrown away. |
| 54 | +** Once requested, the blob will be removed from the cache (i.e. a subsequent call to `createBlobForInput` for the same blob id will open a server-side blob). |
| 55 | +** If the transaction associated with the blob is committed or rolled back (when `COMMITTED` or `ROLLED_BACK` is notified), all blobs of that transaction are removed from the cache. |
| 56 | + |
| 57 | +=== Pending decisions |
| 58 | + |
| 59 | +The following needs to be investigated in more detail before a final decision can be made. |
| 60 | + |
| 61 | +* The local blob may need to be able to open a server-side blob for info requests, or explicitly throw an exception for those cases. |
| 62 | +* We may need some checks on the arguments of the BPB and/or `BlobConfig` to ensure it is suitable to return the local blob, or if a server-side blob needs to be opened, check for a subtype (not available in information items), and possibly the charset id requested. |
| 63 | ++ |
| 64 | +For example, currently Jaybird will set `isc_bpb_source_type` and `isc_bpb_target_type` to the subtype of the field, and for subtype `TEXT` `isc_bpb_target_interp` to the charset id of the field. |
| 65 | +We could assume that if source_type and target_type have the same value, we can use the cached inline blob. |
| 66 | +* Alternative for previous, there needs to be some mechanism so the caller can signal that the cache *should not* be used. |
| 67 | ++ |
| 68 | +This is probably too complex and will never actually be used. |
| 69 | +* Alternative for previous, there needs to be some mechanism so the caller can signal that the cache *should* be used. |
| 70 | ++ |
| 71 | +This is probably too complex, and would only get used by Jaybird itself. |
| 72 | +** A more |
| 73 | + |
| 74 | +=== Rejected decisions |
| 75 | + |
| 76 | +The following decisions were considered, but rejected: |
| 77 | + |
| 78 | +* Make `maxInlineBlobSize` default to `blobBufferSize` for pure Java connections. |
| 79 | ++ |
| 80 | +Using the same default as fbclient will probably result in less surprises for users. |
| 81 | +It also prevents overloading the meaning of `blobBufferSize`. |
| 82 | +* Make `maxBlobCacheSize` set to `0` disable inline blobs as well. |
| 83 | ++ |
| 84 | +Having a single property control enabling and disabling inline blobs is simpler. |
| 85 | + |
| 86 | +== Consequences |
| 87 | + |
| 88 | +A version 19 protocol implementation will be added. |
| 89 | +Inline blobs will be used by default when connecting to Firebird 5.0.3 or higher, but can be disabled by setting `maxInlineBlobSize` to `0`. |
| 90 | + |
| 91 | +[appendix] |
| 92 | +== License Notice |
| 93 | + |
| 94 | +The contents of this Documentation are subject to the Public Documentation License Version 1.0 (the “License”); |
| 95 | +you may only use this Documentation if you comply with the terms of this License. |
| 96 | +A copy of the License is available at https://firebirdsql.org/en/public-documentation-license/. |
| 97 | + |
| 98 | +The Original Documentation is "`jdp-2025-03: Implement Protocol 19`". |
| 99 | +The Initial Writer of the Original Documentation is Mark Rotteveel, Copyright © 2025. |
| 100 | +All Rights Reserved. |
| 101 | +(Initial Writer contact(s): mark (at) lawinegevaar (dot) nl). |
| 102 | + |
| 103 | +//// |
| 104 | +Contributor(s): ______________________________________. |
| 105 | +Portions created by ______ are Copyright © _________ [Insert year(s)]. |
| 106 | +All Rights Reserved. |
| 107 | +(Contributor contact(s): ________________ [Insert hyperlink/alias]). |
| 108 | +//// |
| 109 | + |
| 110 | +The exact file history is recorded in our Git repository; |
| 111 | +see https://github.com/FirebirdSQL/jaybird |
0 commit comments