You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
I've tested this and I'm unable to reproduce it. I get an issue of when one query runs the other doesn't run at all and not the query appending to each other.
The issue is very noticable when trying to do pagination using a single base query.
We initially built pagination like this:
query = client.table(table_name).select("*")
items = []
for offset in range(0, MAX_ROWS, PAGE_SIZE):
next_page = query.range(offset, offset + PAGE_SIZE).execute()
if next_page.data:
items.extend(next_page.data)
...
But we noticed this actually attempts to repeatedly add the offset and limit parameters to the query object, producing HTTP calls such as ?select=*&offset=0&offset=250&offset=500&offset=750&offset=1000&offset=1250&offset=1500&offset=1750&offset=2000&offset=2250&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251.
@DDoerner I've left a repo above showing that I cannot reproduce what the OP posted. Can you clone it and update it to show your issue and then I'll have a look.
I enabled logging so that you can see the two requests, with the second one getting both conditions. Sorry I didn't fork your repo, had this example before I saw your repo 😅
The example your provided doesn't have any data to go with it. This is why I created the example repo as it has data and everything. I'm going to update your example to use data similar to what you originally posted.
Ok tested this and can now replicate the issue. I will reopen this and start looking into fixing this now.
If you are concerned about backwards compatibility, then probably best just to show a warning if execute is called a second time but the resolved query does not match the first request. If select is what actually resolves the query, it's possible that could be tacked on the end if someone needs to create a new query from the chain (not sure if that's actually true, not at my computer to test). Otherwise, this probably just a warning and documentation solution. I believe the documented options would be:
Yes those are the options. I am going to leave this issue open as you have made good suggestions here. I will close this when we have decided on which step to take and update you here.
@silentworks just thought of one non-bc-breaking approach that could also work. The library could introduce some kind of checkpoint chaining function. This would act as a marker to reset the query chain to after an execute. It would look something like this:
"checkpoint" is a terrible name, and there's some edge cases for sure. Not sure if it's worth pursuing at all, but figured I'd throw out the idea all the same 😅
@jscheel I don't think that would be an option. This library would be further deviating away from the JS library which is something we try to keep to a minimum. This would also mean a change in the API in order to introduce something like this and I'm not just talking the external API, the internal API would have to break in order to make this change.
I do think there's a way to fix this without too much trouble. It would be a non backwards compatible change in the sense that the queries would no longer be mutable, but at the same time I hardly believe anyone is relying on them being mutable. I'll investigate later and see what I can find.
@o-santi that change would be welcome as the queries shouldn't have been mutable to begin with, so making them immutable would be fixing a long standing bug rather than breaking the library as such.
Hi @silentworks — I've prepared a comprehensive fix for this that extends the _clone() approach from #1385 to cover every mutation surface, not just the four filter methods it touches.
BaseSelectRequestBuilder: order, limit, offset, range
BaseFilterRequestBuilder: max_affected, or_, match (also fixes a latent chaining bug in match)
BaseRPCRequestBuilder: select, single, maybe_single, csv
AsyncQueryRequestBuilder: select, retry (+ retry on the three sibling builders)
AsyncSelectRequestBuilder: single, maybe_single, csv, text_search, explain (these return different builder types — clone the request first, don't mutate self)
Approach: one module-level _clone_request(request) helper + a small _clone(self) on the builder classes. No decorators (learning from #1521 which was closed). All 196 unit tests pass; mypy + ruff clean.
Since you mentioned on 2026-03-30 that this is scheduled for v3 as a breaking change — would you prefer I open the PR against main now, or wait for a v3 branch to be created? Happy to either route it as-is or gate the immutability behind an opt-in flag if that helps with the v2/v3 transition.
Activity
silentworks commentedon Dec 25, 2024
I've tested this and I'm unable to reproduce it. I get an issue of when one query runs the other doesn't run at all and not the query appending to each other.
jscheel commentedon Dec 25, 2024
@silentworks I'll shoot you a full, reproducible case when I get a moment. Maybe a version mismatch or something.
silentworks commentedon Dec 26, 2024
I created a reproducible with the results I'm getting. You can modify it to see if you can get the results you got and create a PR to the repo https://github.com/silentworks/postgres_py_issue_550
silentworks commentedon Jan 8, 2025
@jscheel did you get around looking at the version I created? or creating a reproducible example repo of the behavior you are getting?
silentworks commentedon Jan 29, 2025
Closing this out as no reply from OP over a month now. Also unable to reproduce the issue.
jscheel commentedon Jan 29, 2025
DDoerner commentedon Apr 1, 2025
The issue is very noticable when trying to do pagination using a single base query.
We initially built pagination like this:
But we noticed this actually attempts to repeatedly add the
offsetandlimitparameters to the query object, producing HTTP calls such as?select=*&offset=0&offset=250&offset=500&offset=750&offset=1000&offset=1250&offset=1500&offset=1750&offset=2000&offset=2250&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251&limit=251.silentworks commentedon Apr 1, 2025
@DDoerner I've left a repo above showing that I cannot reproduce what the OP posted. Can you clone it and update it to show your issue and then I'll have a look.
jscheel commentedon Apr 3, 2025
@silentworks The bug still appears to exist. I've created a reproducible repo for you here: https://github.com/jscheel/supabase-query-builder-bug
I enabled logging so that you can see the two requests, with the second one getting both conditions. Sorry I didn't fork your repo, had this example before I saw your repo 😅
silentworks commentedon Apr 6, 2025
The example your provided doesn't have any data to go with it. This is why I created the example repo as it has data and everything. I'm going to update your example to use data similar to what you originally posted.
Ok tested this and can now replicate the issue. I will reopen this and start looking into fixing this now.
3 remaining items
jscheel commentedon Apr 6, 2025
If you are concerned about backwards compatibility, then probably best just to show a warning if execute is called a second time but the resolved query does not match the first request. If select is what actually resolves the query, it's possible that could be tacked on the end if someone needs to create a new query from the chain (not sure if that's actually true, not at my computer to test). Otherwise, this probably just a warning and documentation solution. I believe the documented options would be:
correct?
silentworks commentedon Apr 6, 2025
Yes those are the options. I am going to leave this issue open as you have made good suggestions here. I will close this when we have decided on which step to take and update you here.
jscheel commentedon Apr 11, 2025
@silentworks just thought of one non-bc-breaking approach that could also work. The library could introduce some kind of checkpoint chaining function. This would act as a marker to reset the query chain to after an execute. It would look something like this:
"checkpoint" is a terrible name, and there's some edge cases for sure. Not sure if it's worth pursuing at all, but figured I'd throw out the idea all the same 😅
silentworks commentedon Apr 17, 2025
@jscheel I don't think that would be an option. This library would be further deviating away from the JS library which is something we try to keep to a minimum. This would also mean a change in the API in order to introduce something like this and I'm not just talking the external API, the internal API would have to break in order to make this change.
o-santi commentedon Oct 9, 2025
I do think there's a way to fix this without too much trouble. It would be a non backwards compatible change in the sense that the queries would no longer be mutable, but at the same time I hardly believe anyone is relying on them being mutable. I'll investigate later and see what I can find.
khushee23 commentedon Oct 18, 2025
i would like to contribute, how can i do so?
silentworks commentedon Oct 31, 2025
@o-santi that change would be welcome as the queries shouldn't have been mutable to begin with, so making them immutable would be fixing a long standing bug rather than breaking the library as such.
dimasd-angga commentedon Mar 30, 2026
is this issue still open? im looking for an issue that i can contribute
silentworks commentedon Mar 30, 2026
@dimasd-angga it is still open but is set to be fixed in v3 of this library due to it being a breaking change.
CAN-Aidoo commentedon Jul 2, 2026
@silentworks I have a comprehensive fix ready, and ask whether you'd prefer it target main now or v3 branch?
CAN-Aidoo commentedon Jul 2, 2026
Hi @silentworks — I've prepared a comprehensive fix for this that extends the
_clone()approach from #1385 to cover every mutation surface, not just the four filter methods it touches.What's covered (that #1385 doesn't):
BaseSelectRequestBuilder:order,limit,offset,rangeBaseFilterRequestBuilder:max_affected,or_,match(also fixes a latent chaining bug inmatch)BaseRPCRequestBuilder:select,single,maybe_single,csvAsyncQueryRequestBuilder:select,retry(+retryon the three sibling builders)AsyncSelectRequestBuilder:single,maybe_single,csv,text_search,explain(these return different builder types — clone the request first, don't mutateself)Approach: one module-level
_clone_request(request)helper + a small_clone(self)on the builder classes. No decorators (learning from #1521 which was closed). All 196 unit tests pass; mypy + ruff clean.Since you mentioned on 2026-03-30 that this is scheduled for v3 as a breaking change — would you prefer I open the PR against
mainnow, or wait for av3branch to be created? Happy to either route it as-is or gate the immutability behind an opt-in flag if that helps with the v2/v3 transition.