feat(postgrest): return a select builder from insert, upsert, update and delete - #1558
Open
karpovantonme wants to merge 1 commit into
Open
Conversation
…and delete
`insert()` and `upsert()` returned a query builder and `update()` and `delete()`
returned a filter builder. Neither exposes `single()`, `maybe_single()`, `csv()`,
`explain()`, `order()`, `limit()` or `range()`, so a chain that reads naturally
in the JS client has no equivalent in Python:
client.from_("users").insert({...}).select().single().execute()
`select()` on those builders returns `self`, so the chain stops at a builder that
never had `single()` to begin with. In supabase-js all four of these methods
return a `PostgrestFilterBuilder`, which carries the transform methods.
Return `SelectRequestBuilder` from all four instead. It already derives from the
query builder and from the filter builder, so this only widens the surface: every
method that worked before still works, on the same object, with the same request
state. Filters after `update()` and `delete()` are unaffected.
The sync package is edited by hand rather than through `make build-sync`. The
generated output currently differs from the committed `_sync` in ways unrelated
to this change (`asyncio.sleep` in place of `time.sleep` in `send_with_retry`,
among others), so regenerating would have pulled unrelated breakage into this PR.
Closes supabase#1553
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.
Closes #1553.
Problem
insert()andupsert()return a query builder,update()anddelete()return a filter builder. Neither type exposessingle(),maybe_single(),csv(),explain(),order(),limit()orrange(), so a chain that reads naturally in the JS client has no equivalent in Python:select()is defined on the query builder and returnsself, which means the chain ends on a builder that never hadsingle()to begin with. In supabase-js all four of these methods return aPostgrestFilterBuilder, and the transform methods hang off it — this is the parity gap the issue describes.Fix
Return
SelectRequestBuilderfrominsert(),upsert(),update()anddelete().SelectRequestBuilderalready derives from the query builder and from the filter builder, so this only widens the surface. Every method that worked before still works, on the same object, with the same request state — filters afterupdate()anddelete()are unaffected, and nothing is removed or renamed. Callers who only use.execute()see no difference.single()on a write is what PostgREST already supports:Prefer: return=representationis set byselect(), andsingle()addsAccept: application/vnd.pgrst.object+json. The added tests assert exactly that, together with the HTTP method stayingPOST/PATCH/DELETE.Note on the sync package
src/postgrest/src/postgrest/_sync/request_builder.pyis edited by hand here rather than regenerated withmake build-sync. Onmain, the generated output differs from the committed_syncin ways unrelated to this change — most visiblysend_with_retrycomes out withasyncio.sleepwhere the committed file hastime.sleep, plus import ordering. Regenerating would have pulled that into this PR, so the same twelve lines were applied to_asyncand_syncinstead. Happy to raise that separately if it is news to you.Verification
make postgrest.pytest— 306 passed (8 new tests, spread across_asyncand_sync).make postgrest.mypy— no issues in 30 source files.uv run ruff checkanduv run ruff format --check— clean.