Skip to content

feat(postgrest): support single()/maybe_single() after insert/upsert select - #1557

Open
tushardev-365 wants to merge 1 commit into
supabase:mainfrom
tushardev-365:fix/1553-insert-select-single
Open

feat(postgrest): support single()/maybe_single() after insert/upsert select#1557
tushardev-365 wants to merge 1 commit into
supabase:mainfrom
tushardev-365:fix/1553-insert-select-single

Conversation

@tushardev-365

Copy link
Copy Markdown
Contributor

What

Closes #1553.

The JS client supports client.from("t").insert(...).select().single(), but the Python client didn't: insert() and upsert() return a *QueryRequestBuilder, whose select() returns self, and single() / maybe_single() only lived on *SelectRequestBuilder. So after an insert/upsert there was no way to get a single-row response.

Change

Move single() and maybe_single() up from *SelectRequestBuilder to the base *QueryRequestBuilder. They're now reachable from every builder select() can return, so all of these work and mirror the JS client:

client.from_("t").insert(row).select().single().execute()
client.from_("t").upsert(row).select().maybe_single().execute()

*SelectRequestBuilder still exposes them via inheritance, so existing select().single() usage is unchanged. The methods only set headers and return the existing single/maybe-single builders, so there's no behavioural change to what single() itself does.

Async is the source of truth; the sync builder and both test files are the unasync-generated mirror.

Testing

Added test_select_single / test_select_maybe_single to the query-request-builder tests (async + sync), asserting select().single() returns the single-request builder with the application/vnd.pgrst.object+json Accept header and select().maybe_single() returns the maybe-single builder. Full postgrest unit suite passes:

90 passed

…select

insert() and upsert() return an *QueryRequestBuilder, whose select()
returns self, so single()/maybe_single() were unreachable and the JS
client chain insert(...).select().single() had no Python equivalent
(supabaseGH-1553). Move single()/maybe_single() up to *QueryRequestBuilder so
they are available on every builder that select() can return, matching
the JS client. Sync code and tests are the unasync-generated mirror.

Closes supabase#1553
@tushardev-365
tushardev-365 requested review from a team and o-santi as code owners July 31, 2026 15:04
@o-santi

o-santi commented Aug 3, 2026

Copy link
Copy Markdown
Contributor

I'm afraid that this might allow .single() for queries that do not make sense to do it. Is this how the JS library is structured?

@tushardev-365

Copy link
Copy Markdown
Contributor Author

Yeah, this matches how JS is structured. There insert/upsert/update/delete/select all return PostgrestFilterBuilder, and single()/maybeSingle() live on its parent PostgrestTransformBuilder, so they're reachable after all of those, same as this PR.

JS doesn't gate the "doesn't make sense" cases either: single() just sets the Accept: application/vnd.pgrst.object+json header and PostgREST decides the result. So this brings us in line with the JS client rather than exposing anything beyond it. Happy to scope it tighter if you'd prefer, though.

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.

Allow selecting single row after INSERT

2 participants