Repository navigation
Conversation
…eads, 64 KiB segments, protocol 19 inline blobs Over a remote link the pure-rust client was round-trip-bound: every BLOB cell cost op_open_blob + N × op_get_segment (1 KiB each!) + op_close_blob, each a full round trip, done serially per cell. A metadata scan of a few thousand objects whose sources live in BLOBs took many minutes. Protocol negotiation - Offer protocol versions 10–16 and 19 (was 10–13). Firebird 3 answers 15, Firebird 4 16, Firebird 5.0.2+ 19. 17/18 are not offered: nothing we send uses op_batch_sync / op_fetch_scroll, and the server picks the highest *offered* version it supports. FB_MAX_PROTOCOL=13 restores the previous negotiation. - op_execute / op_execute2 carry the version-gated trailing fields of P_SQLDATA: p_sqldata_timeout (>= 16), p_sqldata_cursor_flags (>= 18), p_sqldata_inline_blob_size (>= 19). A server at >= 16 blocks reading them, so they must follow the negotiated version exactly. - The attach DPB match covers the new versions (13–19 attach alike); the arm also no longer uses an `if let` match guard, which is not stable Rust and kept the crate from building on a stable toolchain. Blob reads - `resolve_blobs` completes the BLOB columns of a whole fetch batch in a few round trips: opens for 32 blobs in one write, then one op_get_segment per open blob per round (share doubling for blobs that keep going, 32 requests in flight max), closes written without waiting (their responses are consumed lazily, like op_free_statement — the server never defers a close response). Responses arrive strictly in request order, so a FIFO keeps the stream in sync; on a server error every outstanding response is still drained so the connection stays usable. - op_get_segment asks for 65535 bytes (the USHORT maximum) instead of 1024, so a blob under 64 KiB is one segment round trip. - Protocol 19+: the client announces an inline blob size (default 65535, fbclient's default; FB_INLINE_BLOB_SIZE=0 disables) and consumes the op_inline_blob packets the server sends ahead of op_fetch_response / op_sql_response, decoding those blob cells on the spot. Small blobs then cost zero extra round trips. Describe - op_prepare_statement / op_info_sql offer a 64 KiB info buffer (was 1 KiB), so the describe of a wide table no longer comes back truncated and re-requested one round trip at a time.
wire.rs (pure packet tests): protocol offers follow FB_MAX_PROTOCOL with ascending weights; op_execute/op_execute2 trailing fields appear exactly from 16/18/19 and the packet head never moves; op_get_segment caps at the USHORT maximum; segment unframing; op_inline_blob layout; a row decode completes inlined blob columns (text, binary, NULL) and leaves the rest pending. client.rs (pipeline_tests): a scripted Firebird-shaped peer on a loopback socket answers op_fetch / open / get_segment / close / commit strictly in request order, like the server. Covers text, binary, NULL, empty, multi-segment, exactly-one-buffer and multi-round blobs across two batches, lazy-close responses being skipped ahead of a commit, protocol 19 inlining (zero blob ops for small blobs, pipeline for the big one), and a server error in the window (invalid BLOB ID) leaving the connection usable.
The service manager is now reachable without fbclient: op_service_attach after the usual connect/SRP/wire-crypt handshake (the connect packet names the follow-up operation and 'service_mgr'), op_service_start, op_service_info and op_service_detach, with a v2 attach SPB that carries the same auth material as the DPB (plaintext on protocol 10, hashed on 11/12, the SRP proof on 13+ when cont_auth did not verify it). The byte formats — option structs, backup/restore start requests, the isc_info_svc_line / server-version replies — move to rsfbclient_core::services so both clients share them; the native code in rsfbclient::services now delegates to them, and ServiceManager::builder() picks the native client when compiled in and the pure-rust one otherwise (.pure_rust() forces it, .expected_db() names the database for servers with per-database security). start()/query() are public for raw actions. Tests: request/reply byte layouts in core, and a scripted loopback service manager in rsfbclient-rust checking attach, start, line draining, server version and detach.
…alias and field A prepared statement's description now reaches callers: ColumnDesc (core) carries the result-set name, the underlying field, the relation, the context alias it has in the statement (FROM clients c -> C), the owner and the type as the server reported it before coercion. Pure-rust client: isc_info_sql_relation_alias joins the describe items, so the whole description is parsed from the prepare response and describe_statement answers without a round trip. Native client: the XSQLDA names and types are captured at prepare; the context aliases are asked from the library once, on request, and kept with the statement. Facade: Queryable::describe(sql) prepares (through the statement cache, so the query that follows reuses it) and describes without executing; Statement::describe() for an already prepared statement.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.