Skip to content

refactor: tighten the public API and name the placeholder-style test - #5

Merged
iamralch merged 1 commit into
mainfrom
refactor/idiomatic-api
Sep 5, 2026
Merged

refactor: tighten the public API and name the placeholder-style test#5
iamralch merged 1 commit into
mainfrom
refactor/idiomatic-api

Conversation

@iamralch

@iamralch iamralch commented Sep 5, 2026

Copy link
Copy Markdown
Contributor

Follow-up to a read-through for idiomaticity. clippy::all + pedantic were
already clean, and nursery + cargo turned up only redundant_pub_crate and
dependency-version noise from sqlx's tree — so these came from reading, not
from lints.

Dimension is no longer #[non_exhaustive]

An AIP List request has exactly these three query dimensions, and the crate's
scope excludes taking on more. Marking the enum non-exhaustive forced every
downstream match — mapping to a gRPC status, say — to carry a _ arm that can
never fire, and denied them the compile error if a variant ever is added.

Removing the attribute is backwards compatible; adding it back would not be, so
before 0.1.0 ships is the moment.

Query derives Default

Every field already had a Default, and three of the four are absent on a first
unfiltered page:

let query = Query {
    order_by: "name".parse()?,
    columns: VOLUME_COLUMNS,
    ..Default::default()
};

The default Columns map is empty, which rejects every path — the derived
default is the fail-closed one, not an open door.

The placeholder-style check has a name

is_positional, with the reasoning attached: that it infers a behavioural
property from rendered text, that this is a smell, and that the honest fix is a
Dialect::is_positional in sqlx-cel defaulting to exactly this comparison. I'll
raise that upstream separately.

I also walked back a claim I made about the ordinal arithmetic in the positional
branch: param_offset + repeated.len() - 1 is not dead, it is the true
parameter ordinal of the bind. A positional dialect ignores the number, but it
is the honest answer, and the comment now says so instead of the code changing.

The bug this found

Writing the helper, I inverted the comparison. != classifies every numbered
dialect as positional, which repeats binds that are already addressable and
shifts the entire page. Seven existing tests failed, which is a decent answer to
whether they were load-bearing.

The new test pins the case that motivated asking the dialect rather than
hardcoding the three built-ins: SQLite's ?1 form is positional in syntax but
still addressable, so its values must not repeat. A "does the placeholder
contain ?" check would get that wrong.

Testing

34 unit tests, 6 doctests, 6 SQLite round-trips, 6 Postgres round-trips; fmt,
clippy and cargo doc -D warnings clean across the feature matrix.

Four things a read-through turned up.

`Dimension` is no longer `#[non_exhaustive]`. An AIP List request has
exactly these three query dimensions and the crate's scope excludes more,
so a caller mapping them to RPC statuses should get a compile error if
that ever changes rather than a `_` arm that absorbs it silently.
Removing the attribute is backwards compatible; adding it back would not
be, so before 0.1.0 is the moment.

`Query` derives `Default`. Every field already had one, three of the four
are absent on a first unfiltered page, and the derived default is
fail-closed -- an empty column map rejects every path.

The positional-dialect check moves into a named `is_positional` with the
reasoning attached, including that it infers a behavioural property from
rendered text and that the honest fix is a `Dialect::is_positional` in
sqlx-cel.

Writing that helper, I inverted the comparison -- `!=` classifies every
numbered dialect as positional, which repeats binds that are already
addressable and shifts the whole page. Seven tests caught it, which is
the answer to whether the existing ones were load-bearing. The new one
pins the case that motivated asking the dialect at all: SQLite's `?1`
form is positional in syntax but addressable, and must not repeat.
@iamralch
iamralch merged commit 63d6991 into main Sep 5, 2026
4 checks passed
@iamralch
iamralch deleted the refactor/idiomatic-api branch September 5, 2026 09:39
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant