Skip to content

DbClient: typed parameters (DbParameter) and stored-procedure support across all db packages #22

Description

@ccisnedev

Context

Real-world validation against production SQL Server (experiment X4: stored procedures + VARBINARY(MAX) round-trips) surfaced two contract gaps that are identical across all 6 db packages (sqlserver + postgres x TS/Dart/Python). These are limits of the contract itself — no adapter, however good, can work around them.

Gap 1 (G2) — DbCommand.parameters is an untyped positional list

Today: parameters: unknown[] (TS) / List<Object?> (Dart) / tuple[object, ...] (Python). There is no way to declare a parameter's name, direction (input/output/inout), or a type hint. Adapters cannot bind named parameters or read output parameters.

Gap 2 (G3) — DbCommandKind has no procedure

Today: query | execute | batch | scalar. Adapters cannot distinguish stored-procedure execution (e.g. mssql request.execute(spName) vs request.query(sql)), and there is no contract slot for a procedure's return value or output parameters.

Proposal — additive, non-breaking

  • DbParameter value object: { name, value, direction: input|output|inputOutput, typeHint? }. typeHint is a free-form string interpreted by the adapter (e.g. varbinary(max), int) — the package imports nothing from any driver (contracts-only). Static helpers input/output/inputOutput.
  • DbCommand.parameters accepts a mix of raw positional values (current behaviour, preserved) and DbParameter.
  • DbCommandKind.procedure: text = SP name; the adapter decides EXEC/CALL per engine. SP returning rows goes through query(); SP without rows through execute(). No new required methods on DbCommandExecutor (adding one would break every implementer).
  • Optional DbProcedureOutcome { returnValue?: unknown; outputParameters? } on DbRowSet/DbExecutionSummary. returnValue is engine-agnostic (unknown/Object?/object) — the SQL Server integer RETURN is not assumed.

Scope

  • All 6 db packages, with real parity (tests in the 3 SDKs).
  • Reference adapter guide in docs/guides/ (READMEs link to it).
  • ADR formalizing the contracts-only stance (no official driver bindings, ever) + README cleanup removing the implicit "first slice" promise.
  • Target: 0.6.0, coordinated across the 15 packages (single tag, per ADR-0002).

Explicitly out of scope (separate dedicated, breaking iterations)

  • Python db contracts are sync while the rest of the Python SDK is async/ASGI (event-loop blocking) — backlog issue.
  • Dart modular_api_sqlserver hard-depends on dart_odbc via SqlServerMetadataReader, breaking contracts-only — backlog issue (fix by removing the driver from the package, not wrapping it).

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions