Add native RPC calls for arbitrary stored procedures - #7
Open
Tawxyn wants to merge 2 commits into
Open
Conversation
RPC was previously reachable only for the built-in system procedures
(sp_prepare, sp_cursor*, ...), so invoking a user-defined procedure meant
falling back to a generated EXEC batch and losing typed output
parameters, return status, and server messages.
Add Client::call_procedure, built on the existing RPC send path and
response collectors rather than a parallel one: RpcParam gains an
optional type_info, and send_rpc now accepts a procedure name as well as
a numeric proc id.
Public API:
- ProcedureParameter carries an explicit TypeInfo independent of its
value, so a NULL output placeholder can declare a nullable wire type.
Binds positionally by default; .named() binds by name.
- ParameterDirection::{Input, Output, InputOutput}
- ProcedureResult exposes result sets, output values, return status and
informational messages.
- OutputValue::type_info() exposes the server's wire type.
The response is fully buffered, so the connection is reusable as soon as
the call returns, and cancellation works via cancellation_token() as it
does for query/execute.
RETURNSTATUS is surfaced as i32 rather than u32 so negative return codes
round-trip correctly.
Also fix two server-module bugs, both triggered by messages spanning more
than one TDS packet:
- TdsConnection::poll_next returned Poll::Pending after a read that did
not complete a message, with no waker registered, so any multi-packet
request hung forever.
- Multi-packet responses were framed into one accumulating buffer, but
Packet::encode back-patches the length at absolute offsets 2..4,
zeroing the second packet's length and corrupting the first.
BREAKING CHANGE: RpcOption, RpcProcId and RpcStatus move from the crate
root to tiberius::server, alongside the types that expose them
(RpcMessage, DecodedRpcParam). They are no longer part of the
client-facing surface.
Tests: 23 in-process (no DB) and 15 live covering parameter directions,
positional binding, bounded and MAX strings/binary, NULL outputs, numeric
precision/scale, multi-packet payloads (112 KB CLOB / 100 KB BLOB),
multiple result sets, errors, cancellation and connection reuse. Each
in-process server now runs on its own thread; smol's global executor
defaults to a single thread shared by the whole test binary, which
deadlocked once a test moved bulk data.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
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.
Adds Client::call_procedure for invoking named stored procedures through native TDS RPC with positional or named input, output, and input/output parameters.
Preserves declared wire types independently from values so typed NULL outputs, bounded and MAX strings/binary values, and numeric precision/scale round-trip correctly.
Exposes buffered result sets, output values, signed return status, and informational messages while keeping connections reusable after completion, errors, or cancellation.
Fixes multi-packet RPC reads and response framing to prevent hangs and corrupted payloads.