Skip to content

Add parameterized FromRow methods (fetch_one_as/fetch_all_as/stream_as + ToSqlParam params) #137

@StefanSteiner

Description

@StefanSteiner

Summary

There is no method that combines FromRow struct-mapping with
ToSqlParam parameter binding in a single call. Today you can have one or
the other, but not both — so a parameterized query whose results you want as a
struct requires dropping to the raw Row API and mapping by hand.

Current state

Struct-mapping methods take a plain &str (no params):

  • fetch_one_as<T: FromRow>(&self, query: &str)connection.rs:742 / async_connection.rs:359
  • fetch_all_as<T: FromRow>(&self, query: &str)connection.rs:775 / async_connection.rs:375
  • stream_as<T: FromRow>(&self, query: &str)connection.rs:840 / async_connection.rs:435

Parameter-binding methods return raw rows (no FromRow):

  • query_params(&self, query, params: &[&dyn ToSqlParam])Rowsetconnection.rs:1036 / async_connection.rs:574
  • command_params(...) → affected-row count — connection.rs:1089 / async_connection.rs:608

So SELECT * FROM users WHERE org_id = $1Vec<User> isn't expressible in
one call. The workaround is query_params(...) then a manual
RowAccessor/row.get() loop — which defeats the ergonomics FromRow exists
to provide, and is exactly the pattern users reach for now that #65 broadened
ToSqlParam coverage (Numeric/Interval/JSON).

Proposed work

Add parameterized *_as variants mirroring the existing trio, on both the sync
Connection and the async AsyncConnection:

  • fetch_one_as_params<T: FromRow>(&self, query: &str, params: &[&dyn ToSqlParam]) -> Result<T>
  • fetch_all_as_params<T: FromRow>(&self, query: &str, params: &[&dyn ToSqlParam]) -> Result<Vec<T>>
  • stream_as_params<T: FromRow>(&self, query: &str, params: &[&dyn ToSqlParam]) -> Result<impl Iterator<Item = Result<T>>>
    (async: Stream)

Implementation should be small: reuse the existing extended-query path
(prepare_typed + binary bind from query_params) to get the Rowset, then
feed each row through RowAccessor + T::from_row exactly as the current
*_as methods already do. The two halves already exist; this is plumbing them
together, not new protocol work.

Naming is open (_as_params vs _params_as vs an options struct) — pick what
reads best against the existing query_params / fetch_*_as names.

Acceptance criteria

  • Sync + async variants for fetch_one / fetch_all / stream.
  • Round-trip test: parameterized SELECT bound with a ToSqlParam value,
    mapped into a #[derive(FromRow)] struct, asserting the values.
  • Docs/examples updated; the FromRow and ToSqlParam module docs
    cross-reference the new methods.

Context

Surfaced while reviewing FromRow coverage after #65. The mapping layer
(FromRow + #[derive(FromRow)]) and the binding layer (ToSqlParam) are
both complete individually; this is the missing intersection.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions